diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cfcbae6..83fd584 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + '@headlessui/react': + specifier: ^2.2.9 + version: 2.2.9(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@mozilla/readability': specifier: ^0.6.0 version: 0.6.0 @@ -23,6 +26,60 @@ importers: '@tauri-apps/api': specifier: ^2.10.1 version: 2.10.1 + '@tiptap/extension-character-count': + specifier: ^3.20.0 + version: 3.20.0(@tiptap/extensions@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)) + '@tiptap/extension-code-block-lowlight': + specifier: ^3.20.0 + version: 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/extension-code-block@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)(highlight.js@11.11.1)(lowlight@3.3.0) + '@tiptap/extension-color': + specifier: ^3.20.0 + version: 3.20.0(@tiptap/extension-text-style@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))) + '@tiptap/extension-drag-handle-react': + specifier: ^3.20.0 + version: 3.20.0(@tiptap/extension-drag-handle@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/extension-collaboration@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)(@tiptap/y-tiptap@3.0.2(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.6)(y-protocols@1.0.7(yjs@13.6.29))(yjs@13.6.29))(yjs@13.6.29))(@tiptap/extension-node-range@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)(@tiptap/y-tiptap@3.0.2(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.6)(y-protocols@1.0.7(yjs@13.6.29))(yjs@13.6.29)))(@tiptap/pm@3.20.0)(@tiptap/react@3.20.0(@floating-ui/dom@1.7.5)(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@tiptap/extension-emoji': + specifier: ^3.20.0 + version: 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)(@tiptap/suggestion@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0))(emojibase@17.0.0) + '@tiptap/extension-highlight': + specifier: ^3.20.0 + version: 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0)) + '@tiptap/extension-image': + specifier: ^3.20.0 + version: 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0)) + '@tiptap/extension-link': + specifier: ^3.20.0 + version: 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + '@tiptap/extension-placeholder': + specifier: ^3.20.0 + version: 3.20.0(@tiptap/extensions@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)) + '@tiptap/extension-subscript': + specifier: ^3.20.0 + version: 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + '@tiptap/extension-superscript': + specifier: ^3.20.0 + version: 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + '@tiptap/extension-task-item': + specifier: ^3.20.0 + version: 3.20.0(@tiptap/extension-list@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)) + '@tiptap/extension-task-list': + specifier: ^3.20.0 + version: 3.20.0(@tiptap/extension-list@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)) + '@tiptap/extension-text-align': + specifier: ^3.20.0 + version: 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0)) + '@tiptap/extension-text-style': + specifier: ^3.20.0 + version: 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0)) + '@tiptap/extension-underline': + specifier: ^3.20.0 + version: 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0)) + '@tiptap/react': + specifier: ^3.20.0 + version: 3.20.0(@floating-ui/dom@1.7.5)(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@tiptap/starter-kit': + specifier: ^3.20.0 + version: 3.20.0 class-variance-authority: specifier: ^0.7.1 version: 0.7.1 @@ -32,9 +89,15 @@ importers: framer-motion: specifier: ^12.34.1 version: 12.34.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + lowlight: + specifier: ^3.3.0 + version: 3.3.0 lucide-react: specifier: ^0.563.0 version: 0.563.0(react@19.2.4) + mammoth: + specifier: ^1.11.0 + version: 1.11.0 motion: specifier: ^12.34.0 version: 12.34.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -47,9 +110,15 @@ importers: react-dom: specifier: ^19.2.0 version: 19.2.4(react@19.2.4) + react-markdown: + specifier: ^10.1.0 + version: 10.1.0(@types/react@19.2.14)(react@19.2.4) tailwind-merge: specifier: ^3.4.0 version: 3.5.0 + tippy.js: + specifier: ^6.3.7 + version: 6.3.7 devDependencies: '@eslint/js': specifier: ^9.39.1 @@ -466,9 +535,22 @@ packages: react: '>=16.8.0' react-dom: '>=16.8.0' + '@floating-ui/react@0.26.28': + resolution: {integrity: sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + '@floating-ui/utils@0.2.10': resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} + '@headlessui/react@2.2.9': + resolution: {integrity: sha512-Mb+Un58gwBn0/yWZfyrCh0TJyurtT+dETj7YHleylHk5od3dv2XqETPGWMyQ5/7sYN7oWdyM1u9MvC0OC8UmzQ==} + engines: {node: '>=10'} + peerDependencies: + react: ^18 || ^19 || ^19.0.0-rc + react-dom: ^18 || ^19 || ^19.0.0-rc + '@hono/node-server@1.19.9': resolution: {integrity: sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==} engines: {node: '>=18.14.1'} @@ -593,6 +675,9 @@ packages: '@open-draft/until@2.1.0': resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} + '@popperjs/core@2.11.8': + resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} + '@radix-ui/number@1.1.1': resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} @@ -1318,6 +1403,46 @@ packages: '@radix-ui/rect@1.1.1': resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} + '@react-aria/focus@3.21.4': + resolution: {integrity: sha512-6gz+j9ip0/vFRTKJMl3R30MHopn4i19HqqLfSQfElxJD+r9hBnYG1Q6Wd/kl/WRR1+CALn2F+rn06jUnf5sT8Q==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + + '@react-aria/interactions@3.27.0': + resolution: {integrity: sha512-D27pOy+0jIfHK60BB26AgqjjRFOYdvVSkwC31b2LicIzRCSPOSP06V4gMHuGmkhNTF4+YWDi1HHYjxIvMeiSlA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + + '@react-aria/ssr@3.9.10': + resolution: {integrity: sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ==} + engines: {node: '>= 12'} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + + '@react-aria/utils@3.33.0': + resolution: {integrity: sha512-yvz7CMH8d2VjwbSa5nGXqjU031tYhD8ddax95VzJsHSPyqHDEGfxul8RkhGV6oO7bVqZxVs6xY66NIgae+FHjw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + + '@react-stately/flags@3.1.2': + resolution: {integrity: sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg==} + + '@react-stately/utils@3.11.0': + resolution: {integrity: sha512-8LZpYowJ9eZmmYLpudbo/eclIRnbhWIJZ994ncmlKlouNzKohtM8qTC6B1w1pwUbiwGdUoyzLuQbeaIor5Dvcw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + + '@react-types/shared@3.33.0': + resolution: {integrity: sha512-xuUpP6MyuPmJtzNOqF5pzFUIHH2YogyOQfUQHag54PRmWB7AbjuGWBUv0l1UDmz6+AbzAYGmDVAzcRDOu2PFpw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + + '@remirror/core-constants@3.0.0': + resolution: {integrity: sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==} + '@rolldown/pluginutils@1.0.0-rc.3': resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==} @@ -1490,6 +1615,9 @@ packages: resolution: {integrity: sha512-kTD91rZNO4LvRUHv4x3/4hNmsEd2ofkYhuba2VMUPRVef1RCmnHtm7rIws38Fg0yQnOSZOplQzafn0GSiy6GVg==} engines: {node: '>=20.0.0'} + '@swc/helpers@0.5.19': + resolution: {integrity: sha512-QamiFeIK3txNjgUTNppE6MiG3p7TdninpZu0E0PbqVh1a9FNLT2FRhisaa4NcaX52XVhA5l7Pk58Ft7Sqi/2sA==} + '@tailwindcss/node@4.2.1': resolution: {integrity: sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==} @@ -1584,6 +1712,15 @@ packages: peerDependencies: vite: ^5.2.0 || ^6 || ^7 + '@tanstack/react-virtual@3.13.19': + resolution: {integrity: sha512-KzwmU1IbE0IvCZSm6OXkS+kRdrgW2c2P3Ho3NC+zZXWK6oObv/L+lcV/2VuJ+snVESRlMJ+w/fg4WXI/JzoNGQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + '@tanstack/virtual-core@3.13.19': + resolution: {integrity: sha512-/BMP7kNhzKOd7wnDeB8NrIRNLwkf5AhCYCvtfZV2GXWbBieFm/el0n6LOAXlTi6ZwHICSNnQcIxRCWHrLzDY+g==} + '@tauri-apps/api@2.10.1': resolution: {integrity: sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw==} @@ -1663,6 +1800,276 @@ packages: engines: {node: '>= 10'} hasBin: true + '@tiptap/core@3.20.0': + resolution: {integrity: sha512-aC9aROgia/SpJqhsXFiX9TsligL8d+oeoI8W3u00WI45s0VfsqjgeKQLDLF7Tu7hC+7F02teC84SAHuup003VQ==} + peerDependencies: + '@tiptap/pm': ^3.20.0 + + '@tiptap/extension-blockquote@3.20.0': + resolution: {integrity: sha512-LQzn6aGtL4WXz2+rYshl/7/VnP2qJTpD7fWL96GXAzhqviPEY1bJES7poqJb3MU/gzl8VJUVzVzU1VoVfUKlbA==} + peerDependencies: + '@tiptap/core': ^3.20.0 + + '@tiptap/extension-bold@3.20.0': + resolution: {integrity: sha512-sQklEWiyf58yDjiHtm5vmkVjfIc/cBuSusmCsQ0q9vGYnEF1iOHKhGpvnCeEXNeqF3fiJQRlquzt/6ymle3Iwg==} + peerDependencies: + '@tiptap/core': ^3.20.0 + + '@tiptap/extension-bubble-menu@3.20.0': + resolution: {integrity: sha512-MDosUfs8Tj+nwg8RC+wTMWGkLJORXmbR6YZgbiX4hrc7G90Gopdd6kj6ht5/T8t7dLLaX7N0+DEHdUEPGED7dw==} + peerDependencies: + '@tiptap/core': ^3.20.0 + '@tiptap/pm': ^3.20.0 + + '@tiptap/extension-bullet-list@3.20.0': + resolution: {integrity: sha512-OcKMeopBbqWzhSi6o8nNz0aayogg1sfOAhto3NxJu3Ya32dwBFqmHXSYM6uW4jOphNvVPyjiq9aNRh3qTdd1dw==} + peerDependencies: + '@tiptap/extension-list': ^3.20.0 + + '@tiptap/extension-character-count@3.20.0': + resolution: {integrity: sha512-WxE0HgntJfkpaCy7u7ANL7jwqygSIu1wc7eKL78sp1jr0QeyQYj5Addq7h//fpr7OI9+V8v55tM2+qd8RiI77Q==} + peerDependencies: + '@tiptap/extensions': ^3.20.0 + + '@tiptap/extension-code-block-lowlight@3.20.0': + resolution: {integrity: sha512-9lN9rn07lOWkLnByT5C1axtq56MHpOI7MpLaCmX3p+x1bDl6Uvixm6AoBdTLfZUmUYeEFBsf7t5cR+QepMbkiA==} + peerDependencies: + '@tiptap/core': ^3.20.0 + '@tiptap/extension-code-block': ^3.20.0 + '@tiptap/pm': ^3.20.0 + highlight.js: ^11 + lowlight: ^2 || ^3 + + '@tiptap/extension-code-block@3.20.0': + resolution: {integrity: sha512-lBbmNek14aCjrHcBcq3PRqWfNLvC6bcRa2Osc6e/LtmXlcpype4f6n+Yx+WZ+f2uUh0UmDRCz7BEyUETEsDmlQ==} + peerDependencies: + '@tiptap/core': ^3.20.0 + '@tiptap/pm': ^3.20.0 + + '@tiptap/extension-code@3.20.0': + resolution: {integrity: sha512-TYDWFeSQ9umiyrqsT6VecbuhL8XIHkUhO+gEk0sVvH67ZLwjFDhAIIgWIr1/dbIGPcvMZM19E7xUUhAdIaXaOQ==} + peerDependencies: + '@tiptap/core': ^3.20.0 + + '@tiptap/extension-collaboration@3.20.0': + resolution: {integrity: sha512-JItmI4U0i4kqorO114u24hM9k945IdaQ6Uc2DEtPBFFuS8cepJf2zw+ulAT1kAx6ZRiNvNpT9M7w+J0mWRn+Sg==} + peerDependencies: + '@tiptap/core': ^3.20.0 + '@tiptap/pm': ^3.20.0 + '@tiptap/y-tiptap': ^3.0.2 + yjs: ^13 + + '@tiptap/extension-color@3.20.0': + resolution: {integrity: sha512-KGXQ3I18uLHQ61FZpXDu0gH6+0jqmDkVwkPNXmM3oPNDSH80SG5UeZlrXi/PwtlusePJ3dFHtoQ1g6j2bJUssg==} + peerDependencies: + '@tiptap/extension-text-style': ^3.20.0 + + '@tiptap/extension-document@3.20.0': + resolution: {integrity: sha512-oJfLIG3vAtZo/wg29WiBcyWt22KUgddpP8wqtCE+kY5Dw8znLR9ehNmVWlSWJA5OJUMO0ntAHx4bBT+I2MBd5w==} + peerDependencies: + '@tiptap/core': ^3.20.0 + + '@tiptap/extension-drag-handle-react@3.20.0': + resolution: {integrity: sha512-f/rW/S6UiO8RCKgjioUh6zYdNmrSLzOBlKAt87HBN+TYBD54ZIaYTJYFjdPhonTpOgRTlcuUGGFBN+WCsE1+Bw==} + peerDependencies: + '@tiptap/extension-drag-handle': ^3.20.0 + '@tiptap/pm': ^3.20.0 + '@tiptap/react': ^3.20.0 + react: ^16.8 || ^17 || ^18 || ^19 + react-dom: ^16.8 || ^17 || ^18 || ^19 + + '@tiptap/extension-drag-handle@3.20.0': + resolution: {integrity: sha512-CzLRyxZe5QddQey0RUWJUvICyhuRnU/jvzMIYlFvMxM7W97sZ2ggk0cRThlRt2pRUoSr8mmmUnobiorpISmksA==} + peerDependencies: + '@tiptap/core': ^3.20.0 + '@tiptap/extension-collaboration': ^3.20.0 + '@tiptap/extension-node-range': ^3.20.0 + '@tiptap/pm': ^3.20.0 + '@tiptap/y-tiptap': ^3.0.2 + + '@tiptap/extension-dropcursor@3.20.0': + resolution: {integrity: sha512-d+cxplRlktVgZPwatnc34IArlppM0IFKS1J5wLk+ba1jidizsbMVh45tP/BTK2flhyfRqcNoB5R0TArhUpbkNQ==} + peerDependencies: + '@tiptap/extensions': ^3.20.0 + + '@tiptap/extension-emoji@3.20.0': + resolution: {integrity: sha512-a6LgjLQGlKlOJd3o4kcBm8GGAjAO07It84ddmsE68SN4NIb0TVZSDCs4M5FNIN84XCYb4HgbxkyR54xgRwUaNg==} + peerDependencies: + '@tiptap/core': ^3.20.0 + '@tiptap/pm': ^3.20.0 + '@tiptap/suggestion': ^3.20.0 + + '@tiptap/extension-floating-menu@3.20.0': + resolution: {integrity: sha512-rYs4Bv5pVjqZ/2vvR6oe7ammZapkAwN51As/WDbemvYDjfOGRqK58qGauUjYZiDzPOEIzI2mxGwsZ4eJhPW4Ig==} + peerDependencies: + '@floating-ui/dom': ^1.0.0 + '@tiptap/core': ^3.20.0 + '@tiptap/pm': ^3.20.0 + + '@tiptap/extension-gapcursor@3.20.0': + resolution: {integrity: sha512-P/LasfvG9/qFq43ZAlNbAnPnXC+/RJf49buTrhtFvI9Zg0+Lbpjx1oh6oMHB19T88Y28KtrckfFZ8aTSUWDq6w==} + peerDependencies: + '@tiptap/extensions': ^3.20.0 + + '@tiptap/extension-hard-break@3.20.0': + resolution: {integrity: sha512-rqvhMOw4f+XQmEthncbvDjgLH6fz8L9splnKZC7OeS0eX8b0qd7+xI1u5kyxF3KA2Z0BnigES++jjWuecqV6mA==} + peerDependencies: + '@tiptap/core': ^3.20.0 + + '@tiptap/extension-heading@3.20.0': + resolution: {integrity: sha512-JgJhurnCe3eN6a0lEsNQM/46R1bcwzwWWZEFDSb1P9dR8+t1/5v7cMZWsSInpD7R4/74iJn0+M5hcXLwCmBmYA==} + peerDependencies: + '@tiptap/core': ^3.20.0 + + '@tiptap/extension-highlight@3.20.0': + resolution: {integrity: sha512-ANL1wFz0s1ScNR4uBfO0s6Sz+qqGp2u6ynrCVk6TCT3d10CQ+gD1gSDTrVRC3CtlMKtHHH4fYrFAq284+J0gKA==} + peerDependencies: + '@tiptap/core': ^3.20.0 + + '@tiptap/extension-horizontal-rule@3.20.0': + resolution: {integrity: sha512-6uvcutFMv+9wPZgptDkbRDjAm3YVxlibmkhWD5GuaWwS9L/yUtobpI3GycujRSUZ8D3q6Q9J7LqpmQtQRTalWA==} + peerDependencies: + '@tiptap/core': ^3.20.0 + '@tiptap/pm': ^3.20.0 + + '@tiptap/extension-image@3.20.0': + resolution: {integrity: sha512-0t7HYncV0kYEQS79NFczxdlZoZ8zu8X4VavDqt+mbSAUKRq3gCvgtZ5Zyd778sNmtmbz3arxkEYMIVou2swD0g==} + peerDependencies: + '@tiptap/core': ^3.20.0 + + '@tiptap/extension-italic@3.20.0': + resolution: {integrity: sha512-/DhnKQF8yN8RxtuL8abZ28wd5281EaGoE2Oha35zXSOF1vNYnbyt8Ymkv/7u1BcWEWTvRPgaju0YCGXisPRLYw==} + peerDependencies: + '@tiptap/core': ^3.20.0 + + '@tiptap/extension-link@3.20.0': + resolution: {integrity: sha512-qI/5A+R0ZWBxo/8HxSn1uOyr7odr3xHBZ/gzOR1GUJaZqjlJxkWFX0RtXMbLKEGEvT25o345cF7b0wFznEh8qA==} + peerDependencies: + '@tiptap/core': ^3.20.0 + '@tiptap/pm': ^3.20.0 + + '@tiptap/extension-list-item@3.20.0': + resolution: {integrity: sha512-qEtjaaGPuqaFB4VpLrGDoIe9RHnckxPfu6d3rc22ap6TAHCDyRv05CEyJogqccnFceG/v5WN4znUBER8RWnWHA==} + peerDependencies: + '@tiptap/extension-list': ^3.20.0 + + '@tiptap/extension-list-keymap@3.20.0': + resolution: {integrity: sha512-Z4GvKy04Ms4cLFN+CY6wXswd36xYsT2p/YL0V89LYFMZTerOeTjFYlndzn6svqL8NV1PRT5Diw4WTTxJSmcJPA==} + peerDependencies: + '@tiptap/extension-list': ^3.20.0 + + '@tiptap/extension-list@3.20.0': + resolution: {integrity: sha512-+V0/gsVWAv+7vcY0MAe6D52LYTIicMSHw00wz3ISZgprSb2yQhJ4+4gurOnUrQ4Du3AnRQvxPROaofwxIQ66WQ==} + peerDependencies: + '@tiptap/core': ^3.20.0 + '@tiptap/pm': ^3.20.0 + + '@tiptap/extension-node-range@3.20.0': + resolution: {integrity: sha512-XeKKTV88VuJ4Mh0Rxvc/PPzG76cb44sE+rB4u0J/ms63R/WFTm6yJQlCgUVGnGeHleSlrWuZY8gGSuoljmQzqg==} + peerDependencies: + '@tiptap/core': ^3.20.0 + '@tiptap/pm': ^3.20.0 + + '@tiptap/extension-ordered-list@3.20.0': + resolution: {integrity: sha512-jVKnJvrizLk7etwBMfyoj6H2GE4M+PD4k7Bwp6Bh1ohBWtfIA1TlngdS842Mx5i1VB2e3UWIwr8ZH46gl6cwMA==} + peerDependencies: + '@tiptap/extension-list': ^3.20.0 + + '@tiptap/extension-paragraph@3.20.0': + resolution: {integrity: sha512-mM99zK4+RnEXIMCv6akfNATAs0Iija6FgyFA9J9NZ6N4o8y9QiNLLa6HjLpAC+W+VoCgQIekyoF/Q9ftxmAYDQ==} + peerDependencies: + '@tiptap/core': ^3.20.0 + + '@tiptap/extension-placeholder@3.20.0': + resolution: {integrity: sha512-ZhYD3L5m16ydSe2z8vqz+RdtAG/iOQaFHHedFct70tKRoLqi2ajF5kgpemu8DwpaRTcyiCN4G99J/+MqehKNjQ==} + peerDependencies: + '@tiptap/extensions': ^3.20.0 + + '@tiptap/extension-strike@3.20.0': + resolution: {integrity: sha512-0vcTZRRAiDfon3VM1mHBr9EFmTkkUXMhm0Xtdtn0bGe+sIqufyi+hUYTEw93EQOD9XNsPkrud6jzQNYpX2H3AQ==} + peerDependencies: + '@tiptap/core': ^3.20.0 + + '@tiptap/extension-subscript@3.20.0': + resolution: {integrity: sha512-EX3GPey4Gp9W04zM2MsP5OfMnwGtQTh1Q0ZokJAdENHpyXbche9WjK31FTzwEmTSqlU5stSsH5KwhSYlDwm5rA==} + peerDependencies: + '@tiptap/core': ^3.20.0 + '@tiptap/pm': ^3.20.0 + + '@tiptap/extension-superscript@3.20.0': + resolution: {integrity: sha512-NNFv58LM/7JMu4aq9Apq8yuaB8MDL5dvVZ7R6qMuQNZDVGAGgoiBqtglA1RXldNl/9IFcVg67rT8oF86qykYKA==} + peerDependencies: + '@tiptap/core': ^3.20.0 + '@tiptap/pm': ^3.20.0 + + '@tiptap/extension-task-item@3.20.0': + resolution: {integrity: sha512-UArl5ffRNKyiOGJYNtjF50+A0qgYF2DXIEFGyMgJsbp1KYQpDj+UrezWvnGOHZfX64eBWDIO6Bum5jS7o32dYQ==} + peerDependencies: + '@tiptap/extension-list': ^3.20.0 + + '@tiptap/extension-task-list@3.20.0': + resolution: {integrity: sha512-Ab2hfun+5xMG6kQhRjL7s16zTe3XaQRXe3/deGo9hnZrAzTQpWVwDN7H36BX8MemrWnAw3PiuwBH5iOrwNRGjA==} + peerDependencies: + '@tiptap/extension-list': ^3.20.0 + + '@tiptap/extension-text-align@3.20.0': + resolution: {integrity: sha512-4s0r+bovtH6yeGDUD+Ui8j5WOV5koB5P6AuzOMqoLwaFGRSkKf64ly6DXjjmjIgnYCLZN/XO6llaQKVVdvad2g==} + peerDependencies: + '@tiptap/core': ^3.20.0 + + '@tiptap/extension-text-style@3.20.0': + resolution: {integrity: sha512-zyWW1a6W+kaXAn3wv2svJ1XuVMapujftvH7Xn2Q3QmKKiDkO+NiFkrGe8BhMopu8Im51nO3NylIgVA0X1mS1rQ==} + peerDependencies: + '@tiptap/core': ^3.20.0 + + '@tiptap/extension-text@3.20.0': + resolution: {integrity: sha512-tf8bE8tSaOEWabCzPm71xwiUhyMFKqY9jkP5af3Kr1/F45jzZFIQAYZooHI/+zCHRrgJ99MQHKHe1ZNvODrKHQ==} + peerDependencies: + '@tiptap/core': ^3.20.0 + + '@tiptap/extension-underline@3.20.0': + resolution: {integrity: sha512-LzNXuy2jwR/y+ymoUqC72TiGzbOCjioIjsDu0MNYpHuHqTWPK5aV9Mh0nbZcYFy/7fPlV1q0W139EbJeYBZEAQ==} + peerDependencies: + '@tiptap/core': ^3.20.0 + + '@tiptap/extensions@3.20.0': + resolution: {integrity: sha512-HIsXX942w3nbxEQBlMAAR/aa6qiMBEP7CsSMxaxmTIVAmW35p6yUASw6GdV1u0o3lCZjXq2OSRMTskzIqi5uLg==} + peerDependencies: + '@tiptap/core': ^3.20.0 + '@tiptap/pm': ^3.20.0 + + '@tiptap/pm@3.20.0': + resolution: {integrity: sha512-jn+2KnQZn+b+VXr8EFOJKsnjVNaA4diAEr6FOazupMt8W8ro1hfpYtZ25JL87Kao/WbMze55sd8M8BDXLUKu1A==} + + '@tiptap/react@3.20.0': + resolution: {integrity: sha512-jFLNzkmn18zqefJwPje0PPd9VhZ7Oy28YHiSvSc7YpBnQIbuN/HIxZ2lrOsKyEHta0WjRZjfU5X1pGxlbcGwOA==} + peerDependencies: + '@tiptap/core': ^3.20.0 + '@tiptap/pm': ^3.20.0 + '@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 + + '@tiptap/starter-kit@3.20.0': + resolution: {integrity: sha512-W4+1re35pDNY/7rpXVg+OKo/Fa4Gfrn08Bq3E3fzlJw6gjE3tYU8dY9x9vC2rK9pd9NOp7Af11qCFDaWpohXkw==} + + '@tiptap/suggestion@3.20.0': + resolution: {integrity: sha512-OA9Fe+1Q/Ex0ivTcpRcVFiLnNsVdIBmiEoctt/gu4H2ayCYmZ906veioXNdc1m/3MtVVUIuEnvwwsrOZXlfDEw==} + peerDependencies: + '@tiptap/core': ^3.20.0 + '@tiptap/pm': ^3.20.0 + + '@tiptap/y-tiptap@3.0.2': + resolution: {integrity: sha512-flMn/YW6zTbc6cvDaUPh/NfLRTXDIqgpBUkYzM74KA1snqQwhOMjnRcnpu4hDFrTnPO6QGzr99vRyXEA7M44WA==} + 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 + '@ts-morph/common@0.27.0': resolution: {integrity: sha512-Wf29UqxWDpc+i61k3oIOzcUfQt79PIT9y/MWfAGlrkjg6lBC1hwDECLXPVJAhWjiGbfBCxZd65F/LIZF3+jeJQ==} @@ -1678,12 +2085,36 @@ packages: '@types/babel__traverse@7.28.0': resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@types/debug@4.1.12': + resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + + '@types/estree-jsx@1.0.5': + resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} + '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + '@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/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + + '@types/mdurl@2.0.0': + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} + + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + '@types/node@24.10.13': resolution: {integrity: sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg==} @@ -1701,6 +2132,15 @@ packages: '@types/statuses@2.0.6': resolution: {integrity: sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==} + '@types/unist@2.0.11': + resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} + + '@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==} + '@types/validate-npm-package-name@4.0.2': resolution: {integrity: sha512-lrpDziQipxCEeK5kWxvljWYhUvOiB2A9izZd9B2AFarYAkqZshb4lPbRs7zKEic6eGtH8V/2qJW+dPp9OtF6bw==} @@ -1766,12 +2206,19 @@ packages: resolution: {integrity: sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.3.0': + resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + '@vitejs/plugin-react@5.1.4': resolution: {integrity: sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + '@xmldom/xmldom@0.8.11': + resolution: {integrity: sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==} + engines: {node: '>=10.0.0'} + accepts@2.0.0: resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} engines: {node: '>= 0.6'} @@ -1820,6 +2267,9 @@ packages: resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} engines: {node: '>=14'} + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -1831,6 +2281,9 @@ packages: resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} engines: {node: '>=4'} + bail@2.0.2: + resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -1838,11 +2291,17 @@ packages: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + baseline-browser-mapping@2.10.0: resolution: {integrity: sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==} engines: {node: '>=6.0.0'} hasBin: true + bluebird@3.4.7: + resolution: {integrity: sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==} + body-parser@2.2.2: resolution: {integrity: sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==} engines: {node: '>=18'} @@ -1886,6 +2345,9 @@ packages: caniuse-lite@1.0.30001774: resolution: {integrity: sha512-DDdwPGz99nmIEv216hKSgLD+D4ikHQHjBC/seF98N9CPqRX4M5mSxT9eTV6oyisnJcuzxtZy4n17yKKQYmYQOA==} + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -1894,6 +2356,18 @@ packages: resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + + character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + + character-reference-invalid@2.0.1: + resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + class-variance-authority@0.7.1: resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} @@ -1927,6 +2401,9 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + commander@11.1.0: resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} engines: {node: '>=16'} @@ -1961,6 +2438,9 @@ packages: resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} engines: {node: '>=18'} + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + cors@2.8.6: resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} engines: {node: '>= 0.10'} @@ -1974,6 +2454,9 @@ packages: typescript: optional: true + crelt@1.0.6: + resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -1999,6 +2482,9 @@ packages: supports-color: optional: true + decode-named-character-reference@1.3.0: + resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} + dedent@1.7.1: resolution: {integrity: sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==} peerDependencies: @@ -2030,6 +2516,10 @@ packages: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} @@ -2037,14 +2527,23 @@ 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==} + diff@8.0.3: resolution: {integrity: sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==} engines: {node: '>=0.3.1'} + dingbat-to-unicode@1.0.1: + resolution: {integrity: sha512-98l0sW87ZT58pU4i61wa2OHwxbiYSbuxsCBozaVnYX2iCnr3bLM3fIes1/ej7h1YdOKuKt/MLs706TVnALA65w==} + dotenv@17.3.1: resolution: {integrity: sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==} engines: {node: '>=12'} + duck@0.1.12: + resolution: {integrity: sha512-wkctla1O6VfP89gQ+J/yDesM0S7B7XLXjKGzXxMDVFg7uEn706niAtyYovKbyq1oT9YwDcly721/iUWoc8MVRg==} + dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -2065,6 +2564,15 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + emojibase-data@15.3.2: + resolution: {integrity: sha512-TpDyTDDTdqWIJixV5sTA6OQ0P0JfIIeK2tFRR3q56G9LK65ylAZ7z3KyBXokpvTTJ+mLUXQXbLNyVkjvnTLE+A==} + peerDependencies: + emojibase: '*' + + emojibase@17.0.0: + resolution: {integrity: sha512-bXdpf4HPY3p41zK5swVKZdC/VynsMZ4LoLxdYDE+GucqkFwzcM1GVc4ODfYAlwoKaf2U2oNNUoOO78N96ovpBA==} + engines: {node: '>=18.12.0'} + encodeurl@2.0.0: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} @@ -2073,6 +2581,10 @@ packages: resolution: {integrity: sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==} engines: {node: '>=10.13.0'} + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} @@ -2166,6 +2678,9 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} + estree-util-is-identifier-name@3.0.0: + resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} + esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -2200,9 +2715,16 @@ packages: resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} engines: {node: '>= 18'} + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + fast-equals@5.4.0: + resolution: {integrity: sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw==} + engines: {node: '>=6.0.0'} + fast-glob@3.3.3: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} @@ -2378,6 +2900,12 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + hast-util-to-jsx-runtime@2.3.6: + resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==} + + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + headers-polyfill@4.0.3: resolution: {integrity: sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==} @@ -2387,10 +2915,17 @@ packages: hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + highlight.js@11.11.1: + resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==} + engines: {node: '>=12.0.0'} + hono@4.12.2: resolution: {integrity: sha512-gJnaDHXKDayjt8ue0n8Gs0A007yKXj4Xzb8+cNjZeYsSzzwKc0Lr+OZgYwVfB0pHfUs17EPoLvrOsEaJ9mj+Tg==} engines: {node: '>=16.9.0'} + html-url-attributes@3.0.1: + resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==} + http-errors@2.0.1: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} @@ -2423,6 +2958,9 @@ packages: resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} engines: {node: '>= 4'} + immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + import-fresh@3.3.1: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} @@ -2434,6 +2972,9 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + inline-style-parser@0.2.7: + resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==} + ip-address@10.0.1: resolution: {integrity: sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==} engines: {node: '>= 12'} @@ -2442,14 +2983,26 @@ packages: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} + is-alphabetical@2.0.1: + resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} + + is-alphanumerical@2.0.1: + resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + is-decimal@2.0.1: + resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + is-docker@3.0.0: resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} hasBin: true + is-emoji-supported@0.0.5: + resolution: {integrity: sha512-WOlXUhDDHxYqcSmFZis+xWhhqXiK2SU0iYiqmth5Ip0FHLZQAt9rKL5ahnilE8/86WH8tZ3bmNNNC+bTzamqlw==} + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -2462,6 +3015,9 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-hexadecimal@2.0.1: + resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + is-in-ssh@1.0.0: resolution: {integrity: sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==} engines: {node: '>=20'} @@ -2517,6 +3073,9 @@ packages: resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} engines: {node: '>=16'} + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -2524,6 +3083,9 @@ packages: resolution: {integrity: sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==} engines: {node: '>=18'} + isomorphic.js@0.2.5: + resolution: {integrity: sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==} + jiti@2.6.1: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true @@ -2569,6 +3131,9 @@ packages: jsonfile@6.2.0: resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} + jszip@3.10.1: + resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -2584,6 +3149,14 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + lib0@0.2.117: + resolution: {integrity: sha512-DeXj9X5xDCjgKLU/7RR+/HQEVzuuEUiwldwOGsHK/sfAfELGWEyTcf0x+uOvCvK3O2zPmZePXWL85vtia6GyZw==} + engines: {node: '>=16'} + hasBin: true + + lie@3.3.0: + resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} + lightningcss-android-arm64@1.31.1: resolution: {integrity: sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==} engines: {node: '>= 12.0.0'} @@ -2661,6 +3234,12 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + linkify-it@5.0.0: + resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} + + linkifyjs@4.3.2: + resolution: {integrity: sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==} + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -2672,6 +3251,15 @@ packages: resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} engines: {node: '>=18'} + longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + + lop@0.4.2: + resolution: {integrity: sha512-RefILVDQ4DKoRZsJ4Pj22TxE3omDO47yFpkIBoDKzkqPRISs5U1cnAdg/5583YPkWPaLIYHOKRMQSvjFsO26cw==} + + lowlight@3.3.0: + resolution: {integrity: sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ==} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -2683,10 +3271,46 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + mammoth@1.11.0: + resolution: {integrity: sha512-BcEqqY/BOwIcI1iR5tqyVlqc3KIaMRa4egSoK83YAVrBf6+yqdAAbtUcFDCWX8Zef8/fgNZ6rl4VUv+vVX8ddQ==} + engines: {node: '>=12.0.0'} + hasBin: true + + markdown-it@14.1.1: + resolution: {integrity: sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==} + hasBin: true + math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} + mdast-util-from-markdown@2.0.3: + resolution: {integrity: sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==} + + mdast-util-mdx-expression@2.0.1: + resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==} + + mdast-util-mdx-jsx@3.2.0: + resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==} + + mdast-util-mdxjs-esm@2.0.1: + resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==} + + mdast-util-phrasing@4.1.0: + resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} + + mdast-util-to-hast@13.2.1: + resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==} + + mdast-util-to-markdown@2.1.2: + resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==} + + mdast-util-to-string@4.0.0: + resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + + mdurl@2.0.0: + resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + media-typer@1.1.0: resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} engines: {node: '>= 0.8'} @@ -2702,6 +3326,69 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} + micromark-core-commonmark@2.0.3: + resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} + + micromark-factory-destination@2.0.1: + resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==} + + micromark-factory-label@2.0.1: + resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==} + + micromark-factory-space@2.0.1: + resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==} + + micromark-factory-title@2.0.1: + resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==} + + micromark-factory-whitespace@2.0.1: + resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==} + + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + + micromark-util-chunked@2.0.1: + resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==} + + micromark-util-classify-character@2.0.1: + resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==} + + micromark-util-combine-extensions@2.0.1: + resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==} + + micromark-util-decode-numeric-character-reference@2.0.2: + resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==} + + micromark-util-decode-string@2.0.1: + resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==} + + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + + micromark-util-html-tag-name@2.0.1: + resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==} + + micromark-util-normalize-identifier@2.0.1: + resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==} + + micromark-util-resolve-all@2.0.1: + resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==} + + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} + + micromark-util-subtokenize@2.1.0: + resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==} + + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + + micromark-util-types@2.0.2: + resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} + + micromark@4.0.2: + resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} + micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} @@ -2832,6 +3519,9 @@ packages: resolution: {integrity: sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==} engines: {node: '>=20'} + option@0.2.4: + resolution: {integrity: sha512-pkEqbDyl8ou5cpq+VsnQbe/WlEy5qS7xPzMS1U55OCG9KPvwFD46zDbxQIj3egJSFc3D+XhYOPUzz49zQAVy7A==} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -2840,6 +3530,9 @@ packages: resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==} engines: {node: '>=18'} + orderedmap@2.1.1: + resolution: {integrity: sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==} + outvariant@1.4.3: resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} @@ -2854,10 +3547,16 @@ packages: package-manager-detector@1.6.0: resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} + pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} + parse-entities@4.0.2: + resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} + parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} @@ -2877,6 +3576,10 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -2926,14 +3629,82 @@ packages: resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==} engines: {node: '>=18'} + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + prompts@2.4.2: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} + property-information@7.1.0: + resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} + + prosemirror-changeset@2.4.0: + resolution: {integrity: sha512-LvqH2v7Q2SF6yxatuPP2e8vSUKS/L+xAU7dPDC4RMyHMhZoGDfBC74mYuyYF4gLqOEG758wajtyhNnsTkuhvng==} + + 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.2: + resolution: {integrity: sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw==} + + prosemirror-gapcursor@1.4.0: + resolution: {integrity: sha512-z00qvurSdCEWUIulij/isHaqu4uLS8r/Fi61IbjdIPJEonQgggbJsLnstW7Lgdk4zQ68/yr6B6bf7sJXowIgdQ==} + + 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.4: + resolution: {integrity: sha512-D98dm4cQ3Hs6EmjK500TdAOew4Z03EV71ajEFiWra3Upr7diytJsjF4mPV2dW+eK5uNectiRj0xFxYI9NLXDbw==} + + prosemirror-menu@1.3.0: + resolution: {integrity: sha512-TImyPXCHPcDsSka2/lwJ6WjTASr4re/qWq1yoTTuLOqfXucwF6VcRa2LWCkM/EyTD1UO3CUwiH8qURJoWJRxwg==} + + prosemirror-model@1.25.4: + resolution: {integrity: sha512-PIM7E43PBxKce8OQeezAs9j4TP+5yDpZVbuurd1h5phUxEKIu+G2a+EUZzIC5nS1mJktDJWzbqS23n1tsAf5QA==} + + 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.11.0: + resolution: {integrity: sha512-4I7Ce4KpygXb9bkiPS3hTEk4dSHorfRw8uI0pE8IhxlK2GXsqv5tIA7JUSxtSu7u8APVOTtbUBxTmnHIxVkIJw==} + + prosemirror-view@1.41.6: + resolution: {integrity: sha512-mxpcDG4hNQa/CPtzxjdlir5bJFDlm0/x5nGBbStB2BWX+XOQ9M8ekEG+ojqB5BcVu2Rc80/jssCMZzSstJuSYg==} + proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} + 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'} @@ -2971,6 +3742,12 @@ packages: peerDependencies: react: ^19.2.4 + react-markdown@10.1.0: + resolution: {integrity: sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==} + peerDependencies: + '@types/react': '>=18' + react: '>=18' + react-refresh@0.18.0: resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} engines: {node: '>=0.10.0'} @@ -3009,10 +3786,19 @@ packages: resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} engines: {node: '>=0.10.0'} + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + recast@0.23.11: resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==} engines: {node: '>= 4'} + remark-parse@11.0.0: + resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} + + remark-rehype@11.1.2: + resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==} + require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -3041,6 +3827,9 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + rope-sequence@1.3.4: + resolution: {integrity: sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==} + router@2.2.0: resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} engines: {node: '>= 18'} @@ -3052,6 +3841,9 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -3075,6 +3867,9 @@ packages: resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} engines: {node: '>= 18'} + setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} @@ -3124,6 +3919,12 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + statuses@2.0.2: resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} engines: {node: '>= 0.8'} @@ -3143,6 +3944,12 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + stringify-object@5.0.0: resolution: {integrity: sha512-zaJYxz2FtcMb4f+g60KsRNFOpVMUyuJgA51Zi5Z1DOTC3S59+OQiVOzE9GZt0x72uBGWKsQIuBKeF9iusmKFsg==} engines: {node: '>=14.16'} @@ -3171,10 +3978,19 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - supports-color@7.2.0: + style-to-js@1.1.21: + resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==} + + style-to-object@1.0.14: + resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==} + + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + tabbable@6.4.0: + resolution: {integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==} + tagged-tag@1.0.0: resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} engines: {node: '>=20'} @@ -3200,6 +4016,9 @@ packages: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} + tippy.js@6.3.7: + resolution: {integrity: sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==} + tldts-core@7.0.23: resolution: {integrity: sha512-0g9vrtDQLrNIiCj22HSe9d4mLVG3g5ph5DZ8zCKBr4OtrspmNB6ss7hVyzArAeE88ceZocIEGkyW1Ime7fxPtQ==} @@ -3219,6 +4038,12 @@ packages: resolution: {integrity: sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==} engines: {node: '>=16'} + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + + trough@2.2.0: + resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} + ts-api-utils@2.4.0: resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} engines: {node: '>=18.12'} @@ -3262,6 +4087,12 @@ packages: engines: {node: '>=14.17'} hasBin: true + uc.micro@2.1.0: + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + + underscore@1.13.8: + resolution: {integrity: sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==} + undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} @@ -3269,6 +4100,24 @@ packages: resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} engines: {node: '>=18'} + unified@11.0.5: + resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} + + unist-util-is@6.0.1: + resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-parents@6.0.2: + resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==} + + unist-util-visit@5.1.0: + resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} + universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} @@ -3325,6 +4174,12 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} + vfile-message@4.0.3: + resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + vite@7.3.1: resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -3365,6 +4220,9 @@ packages: yaml: optional: true + w3c-keyname@2.2.8: + resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} + web-streams-polyfill@3.3.3: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} @@ -3410,6 +4268,16 @@ packages: resolution: {integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==} engines: {node: '>=20'} + xmlbuilder@10.1.1: + resolution: {integrity: sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg==} + engines: {node: '>=4.0'} + + y-protocols@1.0.7: + resolution: {integrity: sha512-YSVsLoXxO67J6eE/nV4AtFtT3QEotZf5sK5BHxFBXso7VDUT3Tx07IfA6hsu5Q5OmBdMkQVmFZ9QOA7fikWvnw==} + engines: {node: '>=16.0.0', npm: '>=8.0.0'} + peerDependencies: + yjs: ^13.0.0 + y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -3425,6 +4293,10 @@ packages: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} + yjs@13.6.29: + resolution: {integrity: sha512-kHqDPdltoXH+X4w1lVmMtddE3Oeqq48nM40FD5ojTd8xYhQpzIDcfE2keMSU5bAgRPJBe225WTUdyUgj1DtbiQ==} + engines: {node: '>=16.0.0', npm: '>=8.0.0'} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -3454,6 +4326,9 @@ packages: zod@4.3.6: resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + snapshots: '@antfu/ni@25.0.0': @@ -3814,8 +4689,26 @@ snapshots: react: 19.2.4 react-dom: 19.2.4(react@19.2.4) + '@floating-ui/react@0.26.28(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@floating-ui/react-dom': 2.1.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@floating-ui/utils': 0.2.10 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + tabbable: 6.4.0 + '@floating-ui/utils@0.2.10': {} + '@headlessui/react@2.2.9(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@floating-ui/react': 0.26.28(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@react-aria/focus': 3.21.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@react-aria/interactions': 3.27.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@tanstack/react-virtual': 3.13.19(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + use-sync-external-store: 1.6.0(react@19.2.4) + '@hono/node-server@1.19.9(hono@4.12.2)': dependencies: hono: 4.12.2 @@ -3940,6 +4833,8 @@ snapshots: '@open-draft/until@2.1.0': {} + '@popperjs/core@2.11.8': {} + '@radix-ui/number@1.1.1': {} '@radix-ui/primitive@1.1.3': {} @@ -4712,6 +5607,57 @@ snapshots: '@radix-ui/rect@1.1.1': {} + '@react-aria/focus@3.21.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@react-aria/interactions': 3.27.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@react-aria/utils': 3.33.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@react-types/shared': 3.33.0(react@19.2.4) + '@swc/helpers': 0.5.19 + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@react-aria/interactions@3.27.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@react-aria/ssr': 3.9.10(react@19.2.4) + '@react-aria/utils': 3.33.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@react-stately/flags': 3.1.2 + '@react-types/shared': 3.33.0(react@19.2.4) + '@swc/helpers': 0.5.19 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@react-aria/ssr@3.9.10(react@19.2.4)': + dependencies: + '@swc/helpers': 0.5.19 + react: 19.2.4 + + '@react-aria/utils@3.33.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@react-aria/ssr': 3.9.10(react@19.2.4) + '@react-stately/flags': 3.1.2 + '@react-stately/utils': 3.11.0(react@19.2.4) + '@react-types/shared': 3.33.0(react@19.2.4) + '@swc/helpers': 0.5.19 + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@react-stately/flags@3.1.2': + dependencies: + '@swc/helpers': 0.5.19 + + '@react-stately/utils@3.11.0(react@19.2.4)': + dependencies: + '@swc/helpers': 0.5.19 + react: 19.2.4 + + '@react-types/shared@3.33.0(react@19.2.4)': + dependencies: + react: 19.2.4 + + '@remirror/core-constants@3.0.0': {} + '@rolldown/pluginutils@1.0.0-rc.3': {} '@rollup/rollup-android-arm-eabi@4.59.0': @@ -4831,6 +5777,10 @@ snapshots: - bufferutil - utf-8-validate + '@swc/helpers@0.5.19': + dependencies: + tslib: 2.8.1 + '@tailwindcss/node@4.2.1': dependencies: '@jridgewell/remapping': 2.3.5 @@ -4899,6 +5849,14 @@ snapshots: tailwindcss: 4.2.1 vite: 7.3.1(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1) + '@tanstack/react-virtual@3.13.19(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@tanstack/virtual-core': 3.13.19 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@tanstack/virtual-core@3.13.19': {} + '@tauri-apps/api@2.10.1': {} '@tauri-apps/cli-darwin-arm64@2.10.0': @@ -4948,6 +5906,291 @@ snapshots: '@tauri-apps/cli-win32-ia32-msvc': 2.10.0 '@tauri-apps/cli-win32-x64-msvc': 2.10.0 + '@tiptap/core@3.20.0(@tiptap/pm@3.20.0)': + dependencies: + '@tiptap/pm': 3.20.0 + + '@tiptap/extension-blockquote@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + + '@tiptap/extension-bold@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + + '@tiptap/extension-bubble-menu@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)': + dependencies: + '@floating-ui/dom': 1.7.5 + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + '@tiptap/pm': 3.20.0 + optional: true + + '@tiptap/extension-bullet-list@3.20.0(@tiptap/extension-list@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/extension-list': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + + '@tiptap/extension-character-count@3.20.0(@tiptap/extensions@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/extensions': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + + '@tiptap/extension-code-block-lowlight@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/extension-code-block@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)(highlight.js@11.11.1)(lowlight@3.3.0)': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + '@tiptap/extension-code-block': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + '@tiptap/pm': 3.20.0 + highlight.js: 11.11.1 + lowlight: 3.3.0 + + '@tiptap/extension-code-block@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + '@tiptap/pm': 3.20.0 + + '@tiptap/extension-code@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + + '@tiptap/extension-collaboration@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)(@tiptap/y-tiptap@3.0.2(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.6)(y-protocols@1.0.7(yjs@13.6.29))(yjs@13.6.29))(yjs@13.6.29)': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + '@tiptap/pm': 3.20.0 + '@tiptap/y-tiptap': 3.0.2(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.6)(y-protocols@1.0.7(yjs@13.6.29))(yjs@13.6.29) + yjs: 13.6.29 + + '@tiptap/extension-color@3.20.0(@tiptap/extension-text-style@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0)))': + dependencies: + '@tiptap/extension-text-style': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0)) + + '@tiptap/extension-document@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + + '@tiptap/extension-drag-handle-react@3.20.0(@tiptap/extension-drag-handle@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/extension-collaboration@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)(@tiptap/y-tiptap@3.0.2(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.6)(y-protocols@1.0.7(yjs@13.6.29))(yjs@13.6.29))(yjs@13.6.29))(@tiptap/extension-node-range@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)(@tiptap/y-tiptap@3.0.2(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.6)(y-protocols@1.0.7(yjs@13.6.29))(yjs@13.6.29)))(@tiptap/pm@3.20.0)(@tiptap/react@3.20.0(@floating-ui/dom@1.7.5)(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@tiptap/extension-drag-handle': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/extension-collaboration@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)(@tiptap/y-tiptap@3.0.2(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.6)(y-protocols@1.0.7(yjs@13.6.29))(yjs@13.6.29))(yjs@13.6.29))(@tiptap/extension-node-range@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)(@tiptap/y-tiptap@3.0.2(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.6)(y-protocols@1.0.7(yjs@13.6.29))(yjs@13.6.29)) + '@tiptap/pm': 3.20.0 + '@tiptap/react': 3.20.0(@floating-ui/dom@1.7.5)(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@tiptap/extension-drag-handle@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/extension-collaboration@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)(@tiptap/y-tiptap@3.0.2(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.6)(y-protocols@1.0.7(yjs@13.6.29))(yjs@13.6.29))(yjs@13.6.29))(@tiptap/extension-node-range@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)(@tiptap/y-tiptap@3.0.2(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.6)(y-protocols@1.0.7(yjs@13.6.29))(yjs@13.6.29))': + dependencies: + '@floating-ui/dom': 1.7.5 + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + '@tiptap/extension-collaboration': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)(@tiptap/y-tiptap@3.0.2(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.6)(y-protocols@1.0.7(yjs@13.6.29))(yjs@13.6.29))(yjs@13.6.29) + '@tiptap/extension-node-range': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + '@tiptap/pm': 3.20.0 + '@tiptap/y-tiptap': 3.0.2(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.6)(y-protocols@1.0.7(yjs@13.6.29))(yjs@13.6.29) + + '@tiptap/extension-dropcursor@3.20.0(@tiptap/extensions@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/extensions': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + + '@tiptap/extension-emoji@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)(@tiptap/suggestion@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0))(emojibase@17.0.0)': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + '@tiptap/pm': 3.20.0 + '@tiptap/suggestion': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + emoji-regex: 10.6.0 + emojibase-data: 15.3.2(emojibase@17.0.0) + is-emoji-supported: 0.0.5 + transitivePeerDependencies: + - emojibase + + '@tiptap/extension-floating-menu@3.20.0(@floating-ui/dom@1.7.5)(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)': + dependencies: + '@floating-ui/dom': 1.7.5 + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + '@tiptap/pm': 3.20.0 + optional: true + + '@tiptap/extension-gapcursor@3.20.0(@tiptap/extensions@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/extensions': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + + '@tiptap/extension-hard-break@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + + '@tiptap/extension-heading@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + + '@tiptap/extension-highlight@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + + '@tiptap/extension-horizontal-rule@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + '@tiptap/pm': 3.20.0 + + '@tiptap/extension-image@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + + '@tiptap/extension-italic@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + + '@tiptap/extension-link@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + '@tiptap/pm': 3.20.0 + linkifyjs: 4.3.2 + + '@tiptap/extension-list-item@3.20.0(@tiptap/extension-list@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/extension-list': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + + '@tiptap/extension-list-keymap@3.20.0(@tiptap/extension-list@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/extension-list': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + + '@tiptap/extension-list@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + '@tiptap/pm': 3.20.0 + + '@tiptap/extension-node-range@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + '@tiptap/pm': 3.20.0 + + '@tiptap/extension-ordered-list@3.20.0(@tiptap/extension-list@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/extension-list': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + + '@tiptap/extension-paragraph@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + + '@tiptap/extension-placeholder@3.20.0(@tiptap/extensions@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/extensions': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + + '@tiptap/extension-strike@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + + '@tiptap/extension-subscript@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + '@tiptap/pm': 3.20.0 + + '@tiptap/extension-superscript@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + '@tiptap/pm': 3.20.0 + + '@tiptap/extension-task-item@3.20.0(@tiptap/extension-list@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/extension-list': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + + '@tiptap/extension-task-list@3.20.0(@tiptap/extension-list@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/extension-list': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + + '@tiptap/extension-text-align@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + + '@tiptap/extension-text-style@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + + '@tiptap/extension-text@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + + '@tiptap/extension-underline@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + + '@tiptap/extensions@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + '@tiptap/pm': 3.20.0 + + '@tiptap/pm@3.20.0': + dependencies: + prosemirror-changeset: 2.4.0 + prosemirror-collab: 1.3.1 + prosemirror-commands: 1.7.1 + prosemirror-dropcursor: 1.8.2 + prosemirror-gapcursor: 1.4.0 + prosemirror-history: 1.5.0 + prosemirror-inputrules: 1.5.1 + prosemirror-keymap: 1.2.3 + prosemirror-markdown: 1.13.4 + prosemirror-menu: 1.3.0 + prosemirror-model: 1.25.4 + 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.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.6) + prosemirror-transform: 1.11.0 + prosemirror-view: 1.41.6 + + '@tiptap/react@3.20.0(@floating-ui/dom@1.7.5)(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + '@tiptap/pm': 3.20.0 + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + '@types/use-sync-external-store': 0.0.6 + fast-equals: 5.4.0 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + use-sync-external-store: 1.6.0(react@19.2.4) + optionalDependencies: + '@tiptap/extension-bubble-menu': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + '@tiptap/extension-floating-menu': 3.20.0(@floating-ui/dom@1.7.5)(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + transitivePeerDependencies: + - '@floating-ui/dom' + + '@tiptap/starter-kit@3.20.0': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + '@tiptap/extension-blockquote': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0)) + '@tiptap/extension-bold': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0)) + '@tiptap/extension-bullet-list': 3.20.0(@tiptap/extension-list@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)) + '@tiptap/extension-code': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0)) + '@tiptap/extension-code-block': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + '@tiptap/extension-document': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0)) + '@tiptap/extension-dropcursor': 3.20.0(@tiptap/extensions@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)) + '@tiptap/extension-gapcursor': 3.20.0(@tiptap/extensions@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)) + '@tiptap/extension-hard-break': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0)) + '@tiptap/extension-heading': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0)) + '@tiptap/extension-horizontal-rule': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + '@tiptap/extension-italic': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0)) + '@tiptap/extension-link': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + '@tiptap/extension-list': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + '@tiptap/extension-list-item': 3.20.0(@tiptap/extension-list@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)) + '@tiptap/extension-list-keymap': 3.20.0(@tiptap/extension-list@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)) + '@tiptap/extension-ordered-list': 3.20.0(@tiptap/extension-list@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)) + '@tiptap/extension-paragraph': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0)) + '@tiptap/extension-strike': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0)) + '@tiptap/extension-text': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0)) + '@tiptap/extension-underline': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0)) + '@tiptap/extensions': 3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0) + '@tiptap/pm': 3.20.0 + + '@tiptap/suggestion@3.20.0(@tiptap/core@3.20.0(@tiptap/pm@3.20.0))(@tiptap/pm@3.20.0)': + dependencies: + '@tiptap/core': 3.20.0(@tiptap/pm@3.20.0) + '@tiptap/pm': 3.20.0 + + '@tiptap/y-tiptap@3.0.2(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.6)(y-protocols@1.0.7(yjs@13.6.29))(yjs@13.6.29)': + dependencies: + lib0: 0.2.117 + prosemirror-model: 1.25.4 + prosemirror-state: 1.4.4 + prosemirror-view: 1.41.6 + y-protocols: 1.0.7(yjs@13.6.29) + yjs: 13.6.29 + '@ts-morph/common@0.27.0': dependencies: fast-glob: 3.3.3 @@ -4975,10 +6218,37 @@ snapshots: dependencies: '@babel/types': 7.29.0 + '@types/debug@4.1.12': + dependencies: + '@types/ms': 2.1.0 + + '@types/estree-jsx@1.0.5': + dependencies: + '@types/estree': 1.0.8 + '@types/estree@1.0.8': {} + '@types/hast@3.0.4': + 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/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/mdurl@2.0.0': {} + + '@types/ms@2.1.0': {} + '@types/node@24.10.13': dependencies: undici-types: 7.16.0 @@ -4995,6 +6265,12 @@ snapshots: '@types/statuses@2.0.6': {} + '@types/unist@2.0.11': {} + + '@types/unist@3.0.3': {} + + '@types/use-sync-external-store@0.0.6': {} + '@types/validate-npm-package-name@4.0.2': {} '@types/ws@8.18.1': @@ -5092,6 +6368,8 @@ snapshots: '@typescript-eslint/types': 8.56.1 eslint-visitor-keys: 5.0.1 + '@ungap/structured-clone@1.3.0': {} + '@vitejs/plugin-react@5.1.4(vite@7.3.1(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1))': dependencies: '@babel/core': 7.29.0 @@ -5104,6 +6382,8 @@ snapshots: transitivePeerDependencies: - supports-color + '@xmldom/xmldom@0.8.11': {} + accepts@2.0.0: dependencies: mime-types: 3.0.2 @@ -5145,6 +6425,10 @@ snapshots: ansis@4.2.0: {} + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + argparse@2.0.1: {} aria-hidden@1.2.6: @@ -5155,12 +6439,18 @@ snapshots: dependencies: tslib: 2.8.1 + bail@2.0.2: {} + balanced-match@1.0.2: {} balanced-match@4.0.4: {} + base64-js@1.5.1: {} + baseline-browser-mapping@2.10.0: {} + bluebird@3.4.7: {} + body-parser@2.2.2: dependencies: bytes: 3.1.2 @@ -5216,6 +6506,8 @@ snapshots: caniuse-lite@1.0.30001774: {} + ccount@2.0.1: {} + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -5223,6 +6515,14 @@ snapshots: chalk@5.6.2: {} + character-entities-html4@2.1.0: {} + + character-entities-legacy@3.0.0: {} + + character-entities@2.0.2: {} + + character-reference-invalid@2.0.1: {} + class-variance-authority@0.7.1: dependencies: clsx: 2.1.1 @@ -5251,6 +6551,8 @@ snapshots: color-name@1.1.4: {} + comma-separated-tokens@2.0.3: {} + commander@11.1.0: {} commander@14.0.3: {} @@ -5269,6 +6571,8 @@ snapshots: cookie@1.1.1: {} + core-util-is@1.0.3: {} + cors@2.8.6: dependencies: object-assign: 4.1.1 @@ -5283,6 +6587,8 @@ snapshots: optionalDependencies: typescript: 5.9.3 + crelt@1.0.6: {} + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -5299,6 +6605,10 @@ snapshots: dependencies: ms: 2.1.3 + decode-named-character-reference@1.3.0: + dependencies: + character-entities: 2.0.2 + dedent@1.7.1: {} deep-is@0.1.4: {} @@ -5316,14 +6626,26 @@ snapshots: depd@2.0.0: {} + dequal@2.0.3: {} + detect-libc@2.1.2: {} detect-node-es@1.1.0: {} + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + diff@8.0.3: {} + dingbat-to-unicode@1.0.1: {} + dotenv@17.3.1: {} + duck@0.1.12: + dependencies: + underscore: 1.13.8 + dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -5345,6 +6667,12 @@ snapshots: emoji-regex@8.0.0: {} + emojibase-data@15.3.2(emojibase@17.0.0): + dependencies: + emojibase: 17.0.0 + + emojibase@17.0.0: {} + encodeurl@2.0.0: {} enhanced-resolve@5.19.0: @@ -5352,6 +6680,8 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.3.0 + entities@4.5.0: {} + env-paths@2.2.1: {} error-ex@1.3.4: @@ -5486,6 +6816,8 @@ snapshots: estraverse@5.3.0: {} + estree-util-is-identifier-name@3.0.0: {} + esutils@2.0.3: {} etag@1.8.1: {} @@ -5561,8 +6893,12 @@ snapshots: transitivePeerDependencies: - supports-color + extend@3.0.2: {} + fast-deep-equal@3.1.3: {} + fast-equals@5.4.0: {} + fast-glob@3.3.3: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -5718,6 +7054,30 @@ snapshots: dependencies: function-bind: 1.1.2 + hast-util-to-jsx-runtime@2.3.6: + dependencies: + '@types/estree': 1.0.8 + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + hast-util-whitespace: 3.0.0 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.2.0 + mdast-util-mdxjs-esm: 2.0.1 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + style-to-js: 1.1.21 + unist-util-position: 5.0.0 + vfile-message: 4.0.3 + transitivePeerDependencies: + - supports-color + + hast-util-whitespace@3.0.0: + dependencies: + '@types/hast': 3.0.4 + headers-polyfill@4.0.3: {} hermes-estree@0.25.1: {} @@ -5726,8 +7086,12 @@ snapshots: dependencies: hermes-estree: 0.25.1 + highlight.js@11.11.1: {} + hono@4.12.2: {} + html-url-attributes@3.0.1: {} + http-errors@2.0.1: dependencies: depd: 2.0.0 @@ -5757,6 +7121,8 @@ snapshots: ignore@7.0.5: {} + immediate@3.0.6: {} + import-fresh@3.3.1: dependencies: parent-module: 1.0.1 @@ -5766,14 +7132,27 @@ snapshots: inherits@2.0.4: {} + inline-style-parser@0.2.7: {} + ip-address@10.0.1: {} ipaddr.js@1.9.1: {} + is-alphabetical@2.0.1: {} + + is-alphanumerical@2.0.1: + dependencies: + is-alphabetical: 2.0.1 + is-decimal: 2.0.1 + is-arrayish@0.2.1: {} + is-decimal@2.0.1: {} + is-docker@3.0.0: {} + is-emoji-supported@0.0.5: {} + is-extglob@2.1.1: {} is-fullwidth-code-point@3.0.0: {} @@ -5782,6 +7161,8 @@ snapshots: dependencies: is-extglob: 2.1.1 + is-hexadecimal@2.0.1: {} + is-in-ssh@1.0.0: {} is-inside-container@1.0.0: @@ -5814,10 +7195,14 @@ snapshots: dependencies: is-inside-container: 1.0.0 + isarray@1.0.0: {} + isexe@2.0.0: {} isexe@3.1.5: {} + isomorphic.js@0.2.5: {} + jiti@2.6.1: {} jose@6.1.3: {} @@ -5850,6 +7235,13 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 + jszip@3.10.1: + dependencies: + lie: 3.3.0 + pako: 1.0.11 + readable-stream: 2.3.8 + setimmediate: 1.0.5 + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -5863,6 +7255,14 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + lib0@0.2.117: + dependencies: + isomorphic.js: 0.2.5 + + lie@3.3.0: + dependencies: + immediate: 3.0.6 + lightningcss-android-arm64@1.31.1: optional: true @@ -5914,6 +7314,12 @@ snapshots: lines-and-columns@1.2.4: {} + linkify-it@5.0.0: + dependencies: + uc.micro: 2.1.0 + + linkifyjs@4.3.2: {} + locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -5925,6 +7331,20 @@ snapshots: chalk: 5.6.2 is-unicode-supported: 1.3.0 + longest-streak@3.1.0: {} + + lop@0.4.2: + dependencies: + duck: 0.1.12 + option: 0.2.4 + underscore: 1.13.8 + + lowlight@3.3.0: + dependencies: + '@types/hast': 3.0.4 + devlop: 1.1.0 + highlight.js: 11.11.1 + lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -5937,8 +7357,121 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + mammoth@1.11.0: + dependencies: + '@xmldom/xmldom': 0.8.11 + argparse: 1.0.10 + base64-js: 1.5.1 + bluebird: 3.4.7 + dingbat-to-unicode: 1.0.1 + jszip: 3.10.1 + lop: 0.4.2 + path-is-absolute: 1.0.1 + underscore: 1.13.8 + xmlbuilder: 10.1.1 + + markdown-it@14.1.1: + dependencies: + argparse: 2.0.1 + entities: 4.5.0 + linkify-it: 5.0.0 + mdurl: 2.0.0 + punycode.js: 2.3.1 + uc.micro: 2.1.0 + math-intrinsics@1.1.0: {} + mdast-util-from-markdown@2.0.3: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + mdast-util-to-string: 4.0.0 + micromark: 4.0.2 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-decode-string: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + unist-util-stringify-position: 4.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx-expression@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx-jsx@3.2.0: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + parse-entities: 4.0.2 + stringify-entities: 4.0.4 + unist-util-stringify-position: 4.0.0 + vfile-message: 4.0.3 + transitivePeerDependencies: + - supports-color + + mdast-util-mdxjs-esm@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-phrasing@4.1.0: + dependencies: + '@types/mdast': 4.0.4 + unist-util-is: 6.0.1 + + mdast-util-to-hast@13.2.1: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.3.0 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.1 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + + mdast-util-to-markdown@2.1.2: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + longest-streak: 3.1.0 + mdast-util-phrasing: 4.1.0 + mdast-util-to-string: 4.0.0 + micromark-util-classify-character: 2.0.1 + micromark-util-decode-string: 2.0.1 + unist-util-visit: 5.1.0 + zwitch: 2.0.4 + + mdast-util-to-string@4.0.0: + dependencies: + '@types/mdast': 4.0.4 + + mdurl@2.0.0: {} + media-typer@1.1.0: {} merge-descriptors@2.0.0: {} @@ -5947,6 +7480,139 @@ snapshots: merge2@1.4.1: {} + micromark-core-commonmark@2.0.3: + dependencies: + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + micromark-factory-destination: 2.0.1 + micromark-factory-label: 2.0.1 + micromark-factory-space: 2.0.1 + micromark-factory-title: 2.0.1 + micromark-factory-whitespace: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-html-tag-name: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-destination@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-label@2.0.1: + dependencies: + devlop: 1.1.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-space@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-types: 2.0.2 + + micromark-factory-title@2.0.1: + dependencies: + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-whitespace@2.0.1: + dependencies: + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-character@2.1.1: + dependencies: + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-chunked@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-classify-character@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-combine-extensions@2.0.1: + dependencies: + micromark-util-chunked: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-decode-numeric-character-reference@2.0.2: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-decode-string@2.0.1: + dependencies: + decode-named-character-reference: 1.3.0 + micromark-util-character: 2.1.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-symbol: 2.0.1 + + micromark-util-encode@2.0.1: {} + + micromark-util-html-tag-name@2.0.1: {} + + micromark-util-normalize-identifier@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-resolve-all@2.0.1: + dependencies: + micromark-util-types: 2.0.2 + + micromark-util-sanitize-uri@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 + + micromark-util-subtokenize@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-symbol@2.0.1: {} + + micromark-util-types@2.0.2: {} + + micromark@4.0.2: + dependencies: + '@types/debug': 4.1.12 + debug: 4.4.3 + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-combine-extensions: 2.0.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-encode: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + transitivePeerDependencies: + - supports-color + micromatch@4.0.8: dependencies: braces: 3.0.3 @@ -6071,6 +7737,8 @@ snapshots: powershell-utils: 0.1.0 wsl-utils: 0.3.1 + option@0.2.4: {} + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -6092,6 +7760,8 @@ snapshots: string-width: 7.2.0 strip-ansi: 7.1.2 + orderedmap@2.1.1: {} + outvariant@1.4.3: {} p-limit@3.1.0: @@ -6104,10 +7774,22 @@ snapshots: package-manager-detector@1.6.0: {} + pako@1.0.11: {} + parent-module@1.0.1: dependencies: callsites: 3.1.0 + parse-entities@4.0.2: + dependencies: + '@types/unist': 2.0.11 + character-entities-legacy: 3.0.0 + character-reference-invalid: 2.0.1 + decode-named-character-reference: 1.3.0 + is-alphanumerical: 2.0.1 + is-decimal: 2.0.1 + is-hexadecimal: 2.0.1 + parse-json@5.2.0: dependencies: '@babel/code-frame': 7.29.0 @@ -6123,6 +7805,8 @@ snapshots: path-exists@4.0.0: {} + path-is-absolute@1.0.1: {} + path-key@3.1.1: {} path-key@4.0.0: {} @@ -6158,16 +7842,125 @@ snapshots: dependencies: parse-ms: 4.0.0 + process-nextick-args@2.0.1: {} + prompts@2.4.2: dependencies: kleur: 3.0.3 sisteransi: 1.0.5 + property-information@7.1.0: {} + + prosemirror-changeset@2.4.0: + dependencies: + prosemirror-transform: 1.11.0 + + prosemirror-collab@1.3.1: + dependencies: + prosemirror-state: 1.4.4 + + prosemirror-commands@1.7.1: + dependencies: + prosemirror-model: 1.25.4 + prosemirror-state: 1.4.4 + prosemirror-transform: 1.11.0 + + prosemirror-dropcursor@1.8.2: + dependencies: + prosemirror-state: 1.4.4 + prosemirror-transform: 1.11.0 + prosemirror-view: 1.41.6 + + prosemirror-gapcursor@1.4.0: + dependencies: + prosemirror-keymap: 1.2.3 + prosemirror-model: 1.25.4 + prosemirror-state: 1.4.4 + prosemirror-view: 1.41.6 + + prosemirror-history@1.5.0: + dependencies: + prosemirror-state: 1.4.4 + prosemirror-transform: 1.11.0 + prosemirror-view: 1.41.6 + rope-sequence: 1.3.4 + + prosemirror-inputrules@1.5.1: + dependencies: + prosemirror-state: 1.4.4 + prosemirror-transform: 1.11.0 + + prosemirror-keymap@1.2.3: + dependencies: + prosemirror-state: 1.4.4 + w3c-keyname: 2.2.8 + + prosemirror-markdown@1.13.4: + dependencies: + '@types/markdown-it': 14.1.2 + markdown-it: 14.1.1 + prosemirror-model: 1.25.4 + + prosemirror-menu@1.3.0: + dependencies: + crelt: 1.0.6 + prosemirror-commands: 1.7.1 + prosemirror-history: 1.5.0 + prosemirror-state: 1.4.4 + + prosemirror-model@1.25.4: + dependencies: + orderedmap: 2.1.1 + + prosemirror-schema-basic@1.2.4: + dependencies: + prosemirror-model: 1.25.4 + + prosemirror-schema-list@1.5.1: + dependencies: + prosemirror-model: 1.25.4 + prosemirror-state: 1.4.4 + prosemirror-transform: 1.11.0 + + prosemirror-state@1.4.4: + dependencies: + prosemirror-model: 1.25.4 + prosemirror-transform: 1.11.0 + prosemirror-view: 1.41.6 + + prosemirror-tables@1.8.5: + dependencies: + prosemirror-keymap: 1.2.3 + prosemirror-model: 1.25.4 + prosemirror-state: 1.4.4 + prosemirror-transform: 1.11.0 + prosemirror-view: 1.41.6 + + prosemirror-trailing-node@3.0.0(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.6): + dependencies: + '@remirror/core-constants': 3.0.0 + escape-string-regexp: 4.0.0 + prosemirror-model: 1.25.4 + prosemirror-state: 1.4.4 + prosemirror-view: 1.41.6 + + prosemirror-transform@1.11.0: + dependencies: + prosemirror-model: 1.25.4 + + prosemirror-view@1.41.6: + dependencies: + prosemirror-model: 1.25.4 + prosemirror-state: 1.4.4 + prosemirror-transform: 1.11.0 + proxy-addr@2.0.7: dependencies: forwarded: 0.2.0 ipaddr.js: 1.9.1 + punycode.js@2.3.1: {} + punycode@2.3.1: {} qs@6.15.0: @@ -6253,6 +8046,24 @@ snapshots: react: 19.2.4 scheduler: 0.27.0 + react-markdown@10.1.0(@types/react@19.2.14)(react@19.2.4): + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@types/react': 19.2.14 + devlop: 1.1.0 + hast-util-to-jsx-runtime: 2.3.6 + html-url-attributes: 3.0.1 + mdast-util-to-hast: 13.2.1 + react: 19.2.4 + remark-parse: 11.0.0 + remark-rehype: 11.1.2 + unified: 11.0.5 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + react-refresh@0.18.0: {} react-remove-scroll-bar@2.3.8(@types/react@19.2.14)(react@19.2.4): @@ -6284,6 +8095,16 @@ snapshots: react@19.2.4: {} + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + recast@0.23.11: dependencies: ast-types: 0.16.1 @@ -6292,6 +8113,23 @@ snapshots: tiny-invariant: 1.3.3 tslib: 2.8.1 + remark-parse@11.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.3 + micromark-util-types: 2.0.2 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-rehype@11.1.2: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + mdast-util-to-hast: 13.2.1 + unified: 11.0.5 + vfile: 6.0.3 + require-directory@2.1.1: {} require-from-string@2.0.2: {} @@ -6338,6 +8176,8 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.59.0 fsevents: 2.3.3 + rope-sequence@1.3.4: {} + router@2.2.0: dependencies: debug: 4.4.3 @@ -6354,6 +8194,8 @@ snapshots: dependencies: queue-microtask: 1.2.3 + safe-buffer@5.1.2: {} + safer-buffer@2.1.2: {} scheduler@0.27.0: {} @@ -6387,6 +8229,8 @@ snapshots: transitivePeerDependencies: - supports-color + setimmediate@1.0.5: {} + setprototypeof@1.2.0: {} shadcn@3.8.5(@types/node@24.10.13)(typescript@5.9.3): @@ -6477,6 +8321,10 @@ snapshots: source-map@0.6.1: {} + space-separated-tokens@2.0.2: {} + + sprintf-js@1.0.3: {} + statuses@2.0.2: {} stdin-discarder@0.2.2: {} @@ -6495,6 +8343,15 @@ snapshots: get-east-asian-width: 1.5.0 strip-ansi: 7.1.2 + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + stringify-object@5.0.0: dependencies: get-own-enumerable-keys: 1.0.0 @@ -6517,10 +8374,20 @@ snapshots: strip-json-comments@3.1.1: {} + style-to-js@1.1.21: + dependencies: + style-to-object: 1.0.14 + + style-to-object@1.0.14: + dependencies: + inline-style-parser: 0.2.7 + supports-color@7.2.0: dependencies: has-flag: 4.0.0 + tabbable@6.4.0: {} + tagged-tag@1.0.0: {} tailwind-merge@3.5.0: {} @@ -6538,6 +8405,10 @@ snapshots: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 + tippy.js@6.3.7: + dependencies: + '@popperjs/core': 2.11.8 + tldts-core@7.0.23: {} tldts@7.0.23: @@ -6554,6 +8425,10 @@ snapshots: dependencies: tldts: 7.0.23 + trim-lines@3.0.1: {} + + trough@2.2.0: {} + ts-api-utils@2.4.0(typescript@5.9.3): dependencies: typescript: 5.9.3 @@ -6600,10 +8475,47 @@ snapshots: typescript@5.9.3: {} + uc.micro@2.1.0: {} + + underscore@1.13.8: {} + undici-types@7.16.0: {} unicorn-magic@0.3.0: {} + unified@11.0.5: + dependencies: + '@types/unist': 3.0.3 + bail: 2.0.2 + devlop: 1.1.0 + extend: 3.0.2 + is-plain-obj: 4.1.0 + trough: 2.2.0 + vfile: 6.0.3 + + unist-util-is@6.0.1: + dependencies: + '@types/unist': 3.0.3 + + unist-util-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + + unist-util-visit@5.1.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 + universalify@2.0.1: {} unpipe@1.0.0: {} @@ -6645,6 +8557,16 @@ snapshots: vary@1.1.2: {} + vfile-message@4.0.3: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.3 + vite@7.3.1(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1): dependencies: esbuild: 0.27.3 @@ -6659,6 +8581,8 @@ snapshots: jiti: 2.6.1 lightningcss: 1.31.1 + w3c-keyname@2.2.8: {} + web-streams-polyfill@3.3.3: {} which@2.0.2: @@ -6692,6 +8616,13 @@ snapshots: is-wsl: 3.1.1 powershell-utils: 0.1.0 + xmlbuilder@10.1.1: {} + + y-protocols@1.0.7(yjs@13.6.29): + dependencies: + lib0: 0.2.117 + yjs: 13.6.29 + y18n@5.0.8: {} yallist@3.1.1: {} @@ -6708,6 +8639,10 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 + yjs@13.6.29: + dependencies: + lib0: 0.2.117 + yocto-queue@0.1.0: {} yoctocolors-cjs@2.1.3: {} @@ -6725,3 +8660,5 @@ snapshots: zod@3.25.76: {} zod@4.3.6: {} + + zwitch@2.0.4: {} diff --git a/src/App.tsx b/src/App.tsx index a2d5ec6..a4e9a5e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -7,12 +7,14 @@ import { NoteEditor } from './components/NoteEditor'; import { SuperEditor } from './components/SuperEditor'; import { SuperDraw } from './components/SuperDraw'; import { type EditorDoc, loadEditorDocs, saveEditorDocs, loadEditorFolders, saveEditorFolders } from './components/EditorFileList'; +import { type DrawDoc, loadDrawDocs, saveDrawDocs, loadDrawFolders, saveDrawFolders } from './components/DrawFileList'; import { fetchEditorDocs, upsertEditorDoc, removeEditorDoc, updateEditorDocContent, updateEditorDocMeta } from './services/editorDocService'; +import { fetchDrawDocs, upsertDrawDoc, removeDrawDoc, updateDrawDocContent, updateDrawDocMeta } from './services/drawDocService'; import { fetchNotes, upsertNote, removeNote, updateNoteContent, updateNoteMeta } from './services/noteService'; import { BookmarkPanel } from './components/BookmarkPanel'; import { BookmarkReader } from './components/BookmarkReader'; import type { WebBookmark } from './services/bookmarkService'; -import { toggleBookmarkRead, addBookmark } from './services/bookmarkService'; +import { toggleBookmarkRead, addBookmark, fetchBookmarks, updateBookmarkFolder } from './services/bookmarkService'; import { CommandPalette } from './components/CommandPalette'; import { ShortcutsOverlay } from './components/ShortcutsOverlay'; import { useCommands, type Command } from './hooks/useCommands'; @@ -22,6 +24,7 @@ import { useResizablePanels } from './hooks/useResizablePanels'; import { useFeedStore, type FeedStoreCallbacks } from './hooks/useFeedStore'; import { useHighlightStore } from './hooks/useHighlightStore'; import { useAuth } from './contexts/AuthContext'; +import { usePro } from './contexts/ProContext'; import { SyncService, SYNC_ERROR_EVENT } from './services/syncService'; import { getProviderConfig, ProviderSyncService } from './services/providerSync'; import type { NewFeedData } from './components/AddFeedModal'; @@ -51,6 +54,7 @@ function getSyncInterval(): number { export default function App() { const { user } = useAuth(); + const { isPro, showUpgradeModal } = usePro(); const { commands, registerCommands, paletteOpen, closePalette, helpOpen, toggleHelp, closeHelp } = useCommands(); // Sync callbacks wired to SyncService (fire-and-forget, errors logged) @@ -149,16 +153,56 @@ export default function App() { useEffect(() => { saveEditorDocs(editorDocs); }, [editorDocs]); useEffect(() => { saveEditorFolders(editorFolders); }, [editorFolders]); + // ── Draw documents state (SuperDraw mode) ── + const [drawDocs, setDrawDocs] = useState(loadDrawDocs); + const [selectedDrawId, setSelectedDrawId] = useState(null); + const [drawFolders, setDrawFolders] = useState(loadDrawFolders); + const [selectedDrawFolder, setSelectedDrawFolder] = useState(null); + + useEffect(() => { saveDrawDocs(drawDocs); }, [drawDocs]); + useEffect(() => { saveDrawFolders(drawFolders); }, [drawFolders]); + const selectedDoc = useMemo(() => editorDocs.find(d => d.id === selectedDocId) ?? null, [editorDocs, selectedDocId]); + const selectedDraw = useMemo(() => + drawDocs.find(d => d.id === selectedDrawId) ?? null, + [drawDocs, selectedDrawId]); + // Debounce timers for Supabase content updates const contentSaveTimerRef = useRef | null>(null); const noteSaveTimerRef = useRef | null>(null); + const drawSaveTimerRef = useRef | null>(null); // ── Bookmark reader state (SuperBookmark mode) ── const [selectedBookmark, setSelectedBookmark] = useState(null); + const [bookmarkList, setBookmarkList] = useState([]); + + // ── Bookmark folders (localStorage only, like notes) ── + const [bookmarkFolders, setBookmarkFolders] = useState(() => { + try { + const raw = localStorage.getItem('superflux_bookmark_folders'); + return raw ? JSON.parse(raw) : []; + } catch { return []; } + }); + const [bookmarkFolderMap, setBookmarkFolderMap] = useState>(() => { + try { + const raw = localStorage.getItem('superflux_bookmark_folder_map'); + return raw ? JSON.parse(raw) : {}; + } catch { return {}; } + }); + const [selectedBookmarkFolder, setSelectedBookmarkFolder] = useState(null); + + useEffect(() => { + try { localStorage.setItem('superflux_bookmark_folders', JSON.stringify(bookmarkFolders)); } + catch { /* ignore */ } + }, [bookmarkFolders]); + + useEffect(() => { + try { localStorage.setItem('superflux_bookmark_folder_map', JSON.stringify(bookmarkFolderMap)); } + catch { /* ignore */ } + }, [bookmarkFolderMap]); const handleSelectBookmark = useCallback((bk: WebBookmark) => { setSelectedBookmark(bk); @@ -185,6 +229,7 @@ export default function App() { tags: [], note: null, is_read: false, + folder: null, source: 'desktop' as const, }); if (bk) { @@ -192,6 +237,93 @@ export default function App() { } }, [user]); + const handleSaveItemAsBookmark = useCallback(async (item: FeedItem) => { + if (!user) return; + const id = crypto.randomUUID(); + await addBookmark(user.id, { + id, + url: item.url, + title: item.title, + excerpt: item.excerpt || null, + image: item.thumbnail || null, + favicon: null, + author: item.author || null, + site_name: item.feedName || null, + tags: item.tags ?? [], + note: null, + is_read: false, + folder: null, + source: 'desktop' as const, + }); + }, [user]); + + // ── Bookmark folder handlers ── + const handleCreateBookmarkFolder = useCallback((name: string) => { + setBookmarkFolders(prev => [...prev, name]); + }, []); + + const handleRenameBookmarkFolder = useCallback((oldName: string, newName: string) => { + setBookmarkFolders(prev => prev.map(f => f === oldName ? newName : f)); + setBookmarkFolderMap(prev => { + const next = { ...prev }; + const affectedIds: string[] = []; + for (const key of Object.keys(next)) { + if (next[key] === oldName) { + next[key] = newName; + affectedIds.push(key); + } + } + // Sync renamed folder to Supabase for affected bookmarks + if (user) { + affectedIds.forEach(id => updateBookmarkFolder(user.id, id, newName)); + } + return next; + }); + if (selectedBookmarkFolder === oldName) setSelectedBookmarkFolder(newName); + }, [selectedBookmarkFolder, user]); + + const handleDeleteBookmarkFolder = useCallback((name: string) => { + setBookmarkFolders(prev => prev.filter(f => f !== name)); + setBookmarkFolderMap(prev => { + const next = { ...prev }; + const affectedIds: string[] = []; + for (const key of Object.keys(next)) { + if (next[key] === name) { + delete next[key]; + affectedIds.push(key); + } + } + // Remove folder from affected bookmarks in Supabase + if (user) { + affectedIds.forEach(id => updateBookmarkFolder(user.id, id, null)); + } + return next; + }); + if (selectedBookmarkFolder === name) setSelectedBookmarkFolder(null); + }, [selectedBookmarkFolder, user]); + + const handleMoveBookmarkToFolder = useCallback((bookmarkId: string, folder: string | undefined) => { + setBookmarkFolderMap(prev => { + const next = { ...prev }; + if (folder) { + next[bookmarkId] = folder; + } else { + delete next[bookmarkId]; + } + return next; + }); + if (user) updateBookmarkFolder(user.id, bookmarkId, folder ?? null); + }, [user]); + + const bookmarkFolderCounts = useMemo(() => { + const counts: Record = {}; + for (const folder of bookmarkFolders) counts[folder] = 0; + for (const folder of Object.values(bookmarkFolderMap)) { + if (counts[folder] !== undefined) counts[folder]++; + } + return counts; + }, [bookmarkFolders, bookmarkFolderMap]); + const handleAddDoc = useCallback(() => { const doc: EditorDoc = { id: crypto.randomUUID(), @@ -268,6 +400,79 @@ export default function App() { if (user) updateEditorDocMeta(user.id, docId, { folder: folder ?? null }); }, [user]); + // ── Draw document handlers ── + const handleAddDraw = useCallback(() => { + const doc: DrawDoc = { + id: crypto.randomUUID(), + title: 'Sans titre', + content: JSON.stringify({ elements: [], camera: { x: 0, y: 0, zoom: 1 } }), + folder: selectedDrawFolder ?? undefined, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + setDrawDocs(prev => [doc, ...prev]); + setSelectedDrawId(doc.id); + if (user) upsertDrawDoc(user.id, { id: doc.id, title: doc.title, content: doc.content, folder: doc.folder }); + }, [user, selectedDrawFolder]); + + const handleDeleteDraw = useCallback((id: string) => { + setDrawDocs(prev => prev.filter(d => d.id !== id)); + setSelectedDrawId(prev => prev === id ? null : prev); + if (user) removeDrawDoc(user.id, id); + }, [user]); + + const handleRenameDraw = useCallback((id: string, title: string) => { + setDrawDocs(prev => prev.map(d => + d.id === id ? { ...d, title, updatedAt: new Date().toISOString() } : d + )); + if (user) updateDrawDocMeta(user.id, id, { title }); + }, [user]); + + const handleUpdateDrawContent = useCallback((id: string, content: string) => { + setDrawDocs(prev => prev.map(d => + d.id === id ? { ...d, content, updatedAt: new Date().toISOString() } : d + )); + if (user) { + if (drawSaveTimerRef.current) clearTimeout(drawSaveTimerRef.current); + drawSaveTimerRef.current = setTimeout(() => { + updateDrawDocContent(user.id, id, content); + }, 1000); + } + }, [user]); + + const handleCreateDrawFolder = useCallback((name: string) => { + setDrawFolders(prev => [...prev, name]); + }, []); + + const handleRenameDrawFolder = useCallback((oldName: string, newName: string) => { + setDrawFolders(prev => prev.map(f => f === oldName ? newName : f)); + setDrawDocs(prev => prev.map(d => d.folder === oldName ? { ...d, folder: newName } : d)); + if (selectedDrawFolder === oldName) setSelectedDrawFolder(newName); + if (user) { + drawDocs.filter(d => d.folder === oldName).forEach(d => { + updateDrawDocMeta(user.id, d.id, { folder: newName }); + }); + } + }, [selectedDrawFolder, user, drawDocs]); + + const handleDeleteDrawFolder = useCallback((name: string) => { + setDrawFolders(prev => prev.filter(f => f !== name)); + setDrawDocs(prev => prev.map(d => d.folder === name ? { ...d, folder: undefined } : d)); + if (selectedDrawFolder === name) setSelectedDrawFolder(null); + if (user) { + drawDocs.filter(d => d.folder === name).forEach(d => { + updateDrawDocMeta(user.id, d.id, { folder: null }); + }); + } + }, [selectedDrawFolder, user, drawDocs]); + + const handleMoveDrawToFolder = useCallback((docId: string, folder: string | undefined) => { + setDrawDocs(prev => prev.map(d => + d.id === docId ? { ...d, folder, updatedAt: new Date().toISOString() } : d + )); + if (user) updateDrawDocMeta(user.id, docId, { folder: folder ?? null }); + }, [user]); + const selectedNote = useMemo(() => notes.find(n => n.id === selectedNoteId) ?? null, [notes, selectedNoteId]); @@ -384,6 +589,23 @@ export default function App() { if (user) updateNoteMeta(user.id, noteId, { folder: folder ?? null }); }, [user]); + // Refresh bookmark list when switching to bookmark mode + useEffect(() => { + if (brandMode === 'bookmark' && user) { + fetchBookmarks(user.id).then(bks => { + setBookmarkList(bks); + // Also update folder map from Supabase data + const map: Record = {}; + for (const bk of bks) { + if (bk.folder) map[bk.id] = bk.folder; + } + setBookmarkFolderMap(map); + const folders = [...new Set(bks.map(b => b.folder).filter((f): f is string => !!f))]; + if (folders.length > 0) setBookmarkFolders(prev => [...new Set([...prev, ...folders])]); + }).catch(err => console.error('[bookmarks] refresh failed', err)); + } + }, [brandMode, user]); + const handleToggleCollapse = useCallback(() => { setIsCollapsed(prev => !prev); }, []); @@ -484,6 +706,35 @@ export default function App() { } } }).catch(err => console.error('[notes] fetch failed', err)); + + // Fetch bookmarks to rebuild folder assignments from Supabase + fetchBookmarks(userId).then(bks => { + setBookmarkList(bks); + const folders = [...new Set(bks.map(b => b.folder).filter((f): f is string => !!f))]; + if (folders.length > 0) setBookmarkFolders(prev => [...new Set([...prev, ...folders])]); + const map: Record = {}; + for (const bk of bks) { + if (bk.folder) map[bk.id] = bk.folder; + } + setBookmarkFolderMap(map); + }).catch(err => console.error('[bookmarks] fetch folders failed', err)); + + // Fetch draw docs from Supabase + fetchDrawDocs(userId).then(rows => { + if (rows.length > 0) { + const docs: DrawDoc[] = rows.map(r => ({ + id: r.id, + title: r.title, + content: r.content, + folder: r.folder ?? undefined, + createdAt: r.created_at, + updatedAt: r.updated_at, + })); + setDrawDocs(docs); + const folders = [...new Set(docs.map(d => d.folder).filter((f): f is string => !!f))]; + if (folders.length > 0) setDrawFolders(prev => [...new Set([...prev, ...folders])]); + } + }).catch(err => console.error('[draw-docs] fetch failed', err)); } prevUserRef.current = userId; }, [user]); @@ -683,8 +934,14 @@ export default function App() { const handleToggleBrand = useCallback(() => { setBrandTransition(true); // At the midpoint of the animation, switch the mode + // Free users skip editor and draw modes setTimeout(() => { - setBrandMode(m => m === 'flux' ? 'bookmark' : m === 'bookmark' ? 'note' : m === 'note' ? 'editor' : m === 'editor' ? 'draw' : 'flux'); + setBrandMode(m => { + if (isPro) { + return m === 'flux' ? 'bookmark' : m === 'bookmark' ? 'note' : m === 'note' ? 'editor' : m === 'editor' ? 'draw' : 'flux'; + } + return m === 'flux' ? 'bookmark' : m === 'bookmark' ? 'note' : 'flux'; + }); setSelectedNoteId(null); setSelectedBookmark(null); setSearchQuery(''); @@ -693,7 +950,7 @@ export default function App() { setTimeout(() => { setBrandTransition(false); }, 1200); - }, []); + }, [isPro]); const handleCloseSourcePanel = useCallback(() => { setSourcePanelOpen(false); @@ -760,8 +1017,8 @@ export default function App() { { id: 'mode.flux', label: 'Mode SuperFlux', category: 'Modes', shortcut: 'Ctrl+1', action: () => handleBrandSwitch('flux') }, { id: 'mode.bookmark', label: 'Mode SuperBookmark', category: 'Modes', shortcut: 'Ctrl+2', action: () => handleBrandSwitch('bookmark') }, { id: 'mode.note', label: 'Mode SuperNote', category: 'Modes', shortcut: 'Ctrl+3', action: () => handleBrandSwitch('note') }, - { id: 'mode.editor', label: 'Mode SuperEditor', category: 'Modes', shortcut: 'Ctrl+4', action: () => handleBrandSwitch('editor') }, - { id: 'mode.draw', label: 'Mode SuperDraw', category: 'Modes', shortcut: 'Ctrl+5', action: () => handleBrandSwitch('draw') }, + { id: 'mode.editor', label: isPro ? 'Mode SuperEditor' : 'Mode SuperEditor (Pro)', category: 'Modes', shortcut: 'Ctrl+4', action: () => handleBrandSwitch('editor') }, + { id: 'mode.draw', label: isPro ? 'Mode SuperDraw' : 'Mode SuperDraw (Pro)', category: 'Modes', shortcut: 'Ctrl+5', action: () => handleBrandSwitch('draw') }, // ── Feeds ── { id: 'feed.sync', label: 'Synchroniser tous les feeds', category: 'Feeds', shortcut: 'Ctrl+Shift+s', action: () => handleSyncAll() }, @@ -779,13 +1036,17 @@ export default function App() { // Brand switch helper (direct mode, with same animation as toggle) const handleBrandSwitch = useCallback((mode: 'flux' | 'note' | 'bookmark' | 'editor' | 'draw') => { + if (!isPro && (mode === 'editor' || mode === 'draw')) { + showUpgradeModal(); + return; + } setBrandTransition(true); setTimeout(() => { setBrandMode(mode); setSearchQuery(''); }, 600); setTimeout(() => setBrandTransition(false), 1200); - }, []); + }, [isPro, showUpgradeModal]); // When some panels are closed, remaining open panels share the space via flex @@ -875,6 +1136,31 @@ export default function App() { onDeleteEditorFolder={handleDeleteEditorFolder} onMoveDocToFolder={handleMoveDocToFolder} onAddBookmark={handleAddBookmark} + drawDocs={drawDocs} + drawFolders={drawFolders} + selectedDrawId={selectedDrawId} + selectedDrawFolder={selectedDrawFolder} + onSelectDraw={setSelectedDrawId} + onSelectDrawFolder={setSelectedDrawFolder} + onAddDraw={handleAddDraw} + onDeleteDraw={handleDeleteDraw} + onRenameDraw={handleRenameDraw} + onCreateDrawFolder={handleCreateDrawFolder} + onRenameDrawFolder={handleRenameDrawFolder} + onDeleteDrawFolder={handleDeleteDrawFolder} + onMoveDrawToFolder={handleMoveDrawToFolder} + bookmarkFolders={bookmarkFolders} + bookmarkFolderCounts={bookmarkFolderCounts} + selectedBookmarkFolder={selectedBookmarkFolder} + onSelectBookmarkFolder={setSelectedBookmarkFolder} + onCreateBookmarkFolder={handleCreateBookmarkFolder} + onRenameBookmarkFolder={handleRenameBookmarkFolder} + onDeleteBookmarkFolder={handleDeleteBookmarkFolder} + bookmarkItems={bookmarkList} + bookmarkFolderMap={bookmarkFolderMap} + selectedBookmarkId={selectedBookmark?.id ?? null} + onSelectBookmark={handleSelectBookmark} + bookmarkTotalCount={bookmarkList.length} /> {allOpen && handleMouseDown(0, e)} />} @@ -900,7 +1186,11 @@ export default function App() { ) : brandMode === 'bookmark' ? ( ) : brandMode === 'editor' || brandMode === 'draw' ? (
@@ -920,6 +1210,7 @@ export default function App() { onToggleStar={store.toggleStar} onToggleBookmark={store.toggleBookmark} onReorderItems={(showFavorites || showReadLater) ? handleReorderItems : undefined} + onSaveAsBookmark={user ? handleSaveItemAsBookmark : undefined} onClose={handleCloseFeedPanel} /> )} @@ -943,7 +1234,7 @@ export default function App() { ) : brandMode === 'editor' ? ( ) : brandMode === 'draw' ? ( - + ) : brandMode === 'bookmark' ? ( = { interface BookmarkPanelProps { selectedBookmarkId?: string | null; + selectedFolder?: string | null; + bookmarkFolderMap?: Record; + bookmarkFolders?: string[]; onSelectBookmark?: (bookmark: WebBookmark) => void; + onMoveBookmarkToFolder?: (bookmarkId: string, folder: string | undefined) => void; } -export function BookmarkPanel({ selectedBookmarkId, onSelectBookmark }: BookmarkPanelProps) { +type ContextMenuState = + | { kind: 'bookmark'; x: number; y: number; bookmarkId: string } + | null; + +export function BookmarkPanel({ selectedBookmarkId, selectedFolder, bookmarkFolderMap, bookmarkFolders, onSelectBookmark, onMoveBookmarkToFolder }: BookmarkPanelProps) { const { user } = useAuth(); const [bookmarks, setBookmarks] = useState([]); const [loading, setLoading] = useState(true); @@ -27,6 +35,8 @@ export function BookmarkPanel({ selectedBookmarkId, onSelectBookmark }: Bookmark try { return (localStorage.getItem('superflux_bk_viewmode') as ViewMode) || 'cards'; } catch { return 'cards'; } }); + const [contextMenu, setContextMenu] = useState(null); + const [folderSubmenuOpen, setFolderSubmenuOpen] = useState(false); useEffect(() => { try { localStorage.setItem('superflux_bk_viewmode', viewMode); } @@ -43,6 +53,26 @@ export function BookmarkPanel({ selectedBookmarkId, onSelectBookmark }: Bookmark useEffect(() => { load(); }, [load]); + // Close context menu on click/escape + useEffect(() => { + if (!contextMenu) return; + const close = () => { setContextMenu(null); setFolderSubmenuOpen(false); }; + const handleKey = (e: KeyboardEvent) => { if (e.key === 'Escape') close(); }; + document.addEventListener('click', close); + document.addEventListener('keydown', handleKey); + return () => { + document.removeEventListener('click', close); + document.removeEventListener('keydown', handleKey); + }; + }, [contextMenu]); + + const handleContextMenu = useCallback((e: React.MouseEvent, bookmarkId: string) => { + e.preventDefault(); + e.stopPropagation(); + setFolderSubmenuOpen(false); + setContextMenu({ kind: 'bookmark', x: e.clientX, y: e.clientY, bookmarkId }); + }, []); + const handleRemove = async (id: string, e: React.MouseEvent) => { e.stopPropagation(); if (!user) return; @@ -57,9 +87,15 @@ export function BookmarkPanel({ selectedBookmarkId, onSelectBookmark }: Bookmark await toggleBookmarkRead(user.id, id, isRead); }; - const filtered = filter === 'unread' + // Filter by read status + let filtered = filter === 'unread' ? bookmarks.filter(b => !b.is_read) - : bookmarks; + : [...bookmarks]; + + // Filter by selected folder + if (selectedFolder != null && bookmarkFolderMap) { + filtered = filtered.filter(b => bookmarkFolderMap[b.id] === selectedFolder); + } if (!user) { return ( @@ -139,6 +175,7 @@ export function BookmarkPanel({ selectedBookmarkId, onSelectBookmark }: Bookmark key={bk.id} className={`bk-compact-item ${selectedBookmarkId === bk.id ? 'active' : ''} ${bk.is_read ? 'read' : ''}`} onClick={() => onSelectBookmark?.(bk)} + onContextMenu={(e) => handleContextMenu(e, bk.id)} initial={{ opacity: 0, y: 6 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: idx * 0.02, duration: 0.25 }} @@ -192,6 +229,7 @@ export function BookmarkPanel({ selectedBookmarkId, onSelectBookmark }: Bookmark key={bk.id} className={`bk-blob-card ${selectedBookmarkId === bk.id ? 'active' : ''} ${bk.is_read ? 'read' : ''}`} onClick={() => onSelectBookmark?.(bk)} + onContextMenu={(e) => handleContextMenu(e, bk.id)} initial={{ opacity: 0, scale: 0.92 }} animate={{ opacity: 1, scale: 1 }} transition={{ delay: idx * 0.04, duration: 0.35, ease: [0.25, 0.1, 0.25, 1] }} @@ -276,6 +314,63 @@ export function BookmarkPanel({ selectedBookmarkId, onSelectBookmark }: Bookmark
)} + + {/* Bookmark context menu */} + {contextMenu?.kind === 'bookmark' && ( +
e.stopPropagation()} + > +
setFolderSubmenuOpen(true)} + onMouseLeave={() => setFolderSubmenuOpen(false)} + style={{ position: 'relative' }} + > + πŸ“ + Dossier β€Ί + {folderSubmenuOpen && ( +
+ + {(bookmarkFolders ?? []).map(folder => ( + + ))} +
+ )} +
+ +
+ )} ); } diff --git a/src/components/BookmarkSourceList.tsx b/src/components/BookmarkSourceList.tsx new file mode 100644 index 0000000..0ed2895 --- /dev/null +++ b/src/components/BookmarkSourceList.tsx @@ -0,0 +1,272 @@ +import { useState, useCallback, useRef, useEffect } from 'react'; +import { motion, AnimatePresence } from 'motion/react'; +import type { WebBookmark } from '../services/bookmarkService'; + +interface BookmarkSourceListProps { + folders: string[]; + folderCounts: Record; + selectedFolder: string | null; + onSelectFolder: (folder: string | null) => void; + onCreateFolder: (name: string) => void; + onRenameFolder: (oldName: string, newName: string) => void; + onDeleteFolder: (name: string) => void; + bookmarks?: WebBookmark[]; + bookmarkFolderMap?: Record; + selectedBookmarkId?: string | null; + onSelectBookmark?: (bookmark: WebBookmark) => void; + totalCount?: number; +} + +type ContextMenuState = + | { kind: 'folder'; x: number; y: number; folder: string } + | null; + +export function BookmarkSourceList({ + folders, + folderCounts, + selectedFolder, + onSelectFolder, + onCreateFolder, + onRenameFolder, + onDeleteFolder, + bookmarks, + bookmarkFolderMap, + selectedBookmarkId, + onSelectBookmark, + totalCount, +}: BookmarkSourceListProps) { + const [newFolderInput, setNewFolderInput] = useState(false); + const [newFolderName, setNewFolderName] = useState(''); + const [renamingFolder, setRenamingFolder] = useState(null); + const [renameValue, setRenameValue] = useState(''); + const [contextMenu, setContextMenu] = useState(null); + const [expandedFolders, setExpandedFolders] = useState>(new Set()); + const newFolderRef = useRef(null); + const renameRef = useRef(null); + + const toggleFolder = useCallback((folder: string) => { + setExpandedFolders(prev => { + const next = new Set(prev); + if (next.has(folder)) next.delete(folder); + else next.add(folder); + return next; + }); + }, []); + + const handleCreateFolder = useCallback(() => { + const name = newFolderName.trim(); + if (name && !folders.includes(name)) { + onCreateFolder(name); + } + setNewFolderName(''); + setNewFolderInput(false); + }, [newFolderName, folders, onCreateFolder]); + + const handleRename = useCallback(() => { + const name = renameValue.trim(); + if (name && renamingFolder && name !== renamingFolder && !folders.includes(name)) { + onRenameFolder(renamingFolder, name); + // Update expanded key + setExpandedFolders(prev => { + if (!prev.has(renamingFolder)) return prev; + const next = new Set(prev); + next.delete(renamingFolder); + next.add(name); + return next; + }); + } + setRenamingFolder(null); + setRenameValue(''); + }, [renameValue, renamingFolder, folders, onRenameFolder]); + + const handleFolderContext = useCallback((e: React.MouseEvent, folder: string) => { + e.preventDefault(); + e.stopPropagation(); + setContextMenu({ kind: 'folder', x: e.clientX, y: e.clientY, folder }); + }, []); + + useEffect(() => { + if (!contextMenu) return; + const close = () => setContextMenu(null); + const handleKey = (e: KeyboardEvent) => { if (e.key === 'Escape') close(); }; + document.addEventListener('click', close); + document.addEventListener('keydown', handleKey); + return () => { + document.removeEventListener('click', close); + document.removeEventListener('keydown', handleKey); + }; + }, [contextMenu]); + + // Get bookmarks for a given folder + const getBookmarksForFolder = (folder: string): WebBookmark[] => { + if (!bookmarks || !bookmarkFolderMap) return []; + return bookmarks.filter(bk => bookmarkFolderMap[bk.id] === folder); + }; + + return ( +
+ {/* All bookmarks */} + + + {/* New folder button */} + + + {/* New folder input */} + + {newFolderInput && ( + + setNewFolderName(e.target.value)} + onKeyDown={(e) => { + if (e.key === 'Enter') handleCreateFolder(); + if (e.key === 'Escape') { setNewFolderInput(false); setNewFolderName(''); } + }} + onBlur={handleCreateFolder} + placeholder="Nom du dossier" + /> + + )} + + + {/* Folders (expandable, like SuperFlux subfolders) */} + {folders.map((folder) => { + const count = folderCounts[folder] || 0; + const isExpanded = expandedFolders.has(folder); + const folderBookmarks = getBookmarksForFolder(folder); + + return ( +
+ {renamingFolder === folder ? ( +
+ setRenameValue(e.target.value)} + onKeyDown={(e) => { + if (e.key === 'Enter') handleRename(); + if (e.key === 'Escape') { setRenamingFolder(null); setRenameValue(''); } + }} + onBlur={handleRename} + onClick={(e) => e.stopPropagation()} + autoFocus + /> +
+ ) : ( + + )} + + {isExpanded && ( +
+ {folderBookmarks.length === 0 ? ( +
+ Aucun bookmark +
+ ) : ( + folderBookmarks.map((bk) => ( + + )) + )} +
+ )} +
+ ); + })} + + {/* Folder context menu */} + {contextMenu?.kind === 'folder' && ( +
e.stopPropagation()} + > + + +
+ )} +
+ ); +} diff --git a/src/components/DrawFileList.tsx b/src/components/DrawFileList.tsx new file mode 100644 index 0000000..328e4d8 --- /dev/null +++ b/src/components/DrawFileList.tsx @@ -0,0 +1,439 @@ +import { useState, useCallback, useRef, useEffect } from 'react'; +import { motion, AnimatePresence } from 'motion/react'; + +export interface DrawDoc { + id: string; + title: string; + content: string; // JSON string of { elements, camera } + folder?: string; + createdAt: string; + updatedAt: string; +} + +const STORAGE_KEY = 'superflux_draw_docs'; +const FOLDERS_KEY = 'superflux_draw_folders'; + +export function loadDrawDocs(): DrawDoc[] { + try { + const raw = localStorage.getItem(STORAGE_KEY); + return raw ? JSON.parse(raw) : []; + } catch { return []; } +} + +export function saveDrawDocs(docs: DrawDoc[]) { + try { localStorage.setItem(STORAGE_KEY, JSON.stringify(docs)); } + catch { /* ignore */ } +} + +export function loadDrawFolders(): string[] { + try { + const raw = localStorage.getItem(FOLDERS_KEY); + return raw ? JSON.parse(raw) : []; + } catch { return []; } +} + +export function saveDrawFolders(folders: string[]) { + try { localStorage.setItem(FOLDERS_KEY, JSON.stringify(folders)); } + catch { /* ignore */ } +} + +interface DrawFileListProps { + docs: DrawDoc[]; + folders: string[]; + selectedDocId: string | null; + selectedFolder: string | null; + onSelectDoc: (id: string) => void; + onSelectFolder: (folder: string | null) => void; + onAddDoc: () => void; + onDeleteDoc: (id: string) => void; + onRenameDoc: (id: string, title: string) => void; + onCreateFolder: (name: string) => void; + onRenameFolder: (oldName: string, newName: string) => void; + onDeleteFolder: (name: string) => void; + onMoveDocToFolder: (docId: string, folder: string | undefined) => void; +} + +type ContextMenuState = + | { kind: 'doc'; x: number; y: number; docId: string; currentFolder?: string } + | { kind: 'folder'; x: number; y: number; folder: string } + | null; + +export function DrawFileList({ + docs, + folders, + selectedDocId, + selectedFolder, + onSelectDoc, + onSelectFolder, + onAddDoc, + onDeleteDoc, + onRenameDoc, + onCreateFolder, + onRenameFolder, + onDeleteFolder, + onMoveDocToFolder, +}: DrawFileListProps) { + const [expandedFolders, setExpandedFolders] = useState>(new Set(folders)); + const [newFolderInput, setNewFolderInput] = useState(false); + const [newFolderName, setNewFolderName] = useState(''); + const [renamingFolder, setRenamingFolder] = useState(null); + const [renameValue, setRenameValue] = useState(''); + const [renamingDocId, setRenamingDocId] = useState(null); + const [docRenameValue, setDocRenameValue] = useState(''); + const [contextMenu, setContextMenu] = useState(null); + const [moveSubmenuOpen, setMoveSubmenuOpen] = useState(false); + const newFolderRef = useRef(null); + const renameRef = useRef(null); + + const toggleFolder = useCallback((folder: string) => { + setExpandedFolders(prev => { + const next = new Set(prev); + if (next.has(folder)) next.delete(folder); + else next.add(folder); + return next; + }); + }, []); + + const handleCreateFolder = useCallback(() => { + const name = newFolderName.trim(); + if (name && !folders.includes(name)) { + onCreateFolder(name); + setExpandedFolders(prev => new Set(prev).add(name)); + } + setNewFolderName(''); + setNewFolderInput(false); + }, [newFolderName, folders, onCreateFolder]); + + const handleRenameFolder = useCallback(() => { + const name = renameValue.trim(); + if (name && renamingFolder && name !== renamingFolder && !folders.includes(name)) { + onRenameFolder(renamingFolder, name); + } + setRenamingFolder(null); + setRenameValue(''); + }, [renameValue, renamingFolder, folders, onRenameFolder]); + + const handleDocRename = useCallback(() => { + if (renamingDocId && docRenameValue.trim()) { + onRenameDoc(renamingDocId, docRenameValue.trim()); + } + setRenamingDocId(null); + setDocRenameValue(''); + }, [renamingDocId, docRenameValue, onRenameDoc]); + + const handleDocContext = useCallback((e: React.MouseEvent, docId: string, currentFolder?: string) => { + e.preventDefault(); + e.stopPropagation(); + setMoveSubmenuOpen(false); + setContextMenu({ kind: 'doc', x: e.clientX, y: e.clientY, docId, currentFolder }); + }, []); + + const handleFolderContext = useCallback((e: React.MouseEvent, folder: string) => { + e.preventDefault(); + e.stopPropagation(); + setMoveSubmenuOpen(false); + setContextMenu({ kind: 'folder', x: e.clientX, y: e.clientY, folder }); + }, []); + + const closeContextMenu = useCallback(() => { + setContextMenu(null); + setMoveSubmenuOpen(false); + }, []); + + useEffect(() => { + if (!contextMenu) return; + const close = () => { setContextMenu(null); setMoveSubmenuOpen(false); }; + const handleKey = (e: KeyboardEvent) => { if (e.key === 'Escape') close(); }; + document.addEventListener('click', close); + document.addEventListener('keydown', handleKey); + return () => { + document.removeEventListener('click', close); + document.removeEventListener('keydown', handleKey); + }; + }, [contextMenu]); + + const sorted = [...docs].sort((a, b) => + new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime() + ); + const rootDocs = sorted.filter(d => !d.folder); + + const renderDocItem = (doc: DrawDoc) => ( +
onSelectDoc(doc.id)} + onContextMenu={(e) => handleDocContext(e, doc.id, doc.folder)} + > + {renamingDocId === doc.id ? ( +
e.stopPropagation()}> + setDocRenameValue(e.target.value)} + onKeyDown={e => { + if (e.key === 'Enter') handleDocRename(); + if (e.key === 'Escape') { setRenamingDocId(null); setDocRenameValue(''); } + }} + onBlur={handleDocRename} + autoFocus + /> +
+ ) : ( + <> + 🎨 + {doc.title || 'Sans titre'} + + )} +
+ ); + + return ( +
+ {/* All drawings button */} + + + {/* New drawing button */} + + + {/* New folder button */} + + + {/* New folder input */} + + {newFolderInput && ( + + setNewFolderName(e.target.value)} + onKeyDown={(e) => { + if (e.key === 'Enter') handleCreateFolder(); + if (e.key === 'Escape') { setNewFolderInput(false); setNewFolderName(''); } + }} + onBlur={handleCreateFolder} + placeholder="Nom du dossier" + /> + + )} + + + {/* Root docs (no folder) */} +
+ {rootDocs.map(renderDocItem)} +
+ + {/* Folders */} + {folders.map((folder, idx) => { + const folderDocs = sorted.filter(d => d.folder === folder); + const isExpanded = expandedFolders.has(folder); + + return ( + +
{ onSelectFolder(folder); if (!isExpanded) toggleFolder(folder); }} + onContextMenu={(e) => handleFolderContext(e, folder)} + > + πŸ“ + {renamingFolder === folder ? ( + setRenameValue(e.target.value)} + onKeyDown={(e) => { + if (e.key === 'Enter') handleRenameFolder(); + if (e.key === 'Escape') { setRenamingFolder(null); setRenameValue(''); } + }} + onBlur={handleRenameFolder} + onClick={(e) => e.stopPropagation()} + autoFocus + /> + ) : ( + {folder} + )} + {folderDocs.length} + { e.stopPropagation(); toggleFolder(folder); }} + > + β€Ί + +
+ + + {isExpanded && ( + + {folderDocs.map(renderDocItem)} + {folderDocs.length === 0 && ( +
Dossier vide
+ )} +
+ )} +
+
+ ); + })} + + {/* Empty state */} + {docs.length === 0 && folders.length === 0 && ( +
+ Aucun schema +
+ )} + + {/* Document context menu */} + {contextMenu?.kind === 'doc' && ( +
e.stopPropagation()} + > + + + {folders.length > 0 && ( +
+ + + {moveSubmenuOpen && ( +
+ {contextMenu.currentFolder && ( + + )} + {folders + .filter(f => f !== contextMenu.currentFolder) + .map(folder => ( + + ))} +
+ )} +
+ )} + + +
+ )} + + {/* Folder context menu */} + {contextMenu?.kind === 'folder' && ( +
e.stopPropagation()} + > + + +
+ )} +
+ ); +} diff --git a/src/components/FeedPanel.tsx b/src/components/FeedPanel.tsx index c8ad2d6..f70788a 100644 --- a/src/components/FeedPanel.tsx +++ b/src/components/FeedPanel.tsx @@ -46,6 +46,7 @@ interface FeedPanelProps { onToggleStar: (itemId: string) => void; onToggleBookmark: (itemId: string) => void; onReorderItems?: (orderedIds: string[]) => void; + onSaveAsBookmark?: (item: FeedItem) => void; onClose: () => void; } @@ -115,7 +116,7 @@ function findFeedName(categories: FeedCategory[], feedId: string): string | null return null; } -export function FeedPanel({ categories, items, selectedFeedId, selectedSource, selectedItemId, showFavorites, showReadLater, onSelectItem, onMarkAllAsRead, onMarkAllAsUnread, onToggleRead, onToggleStar, onToggleBookmark, onReorderItems, onClose }: FeedPanelProps) { +export function FeedPanel({ categories, items, selectedFeedId, selectedSource, selectedItemId, showFavorites, showReadLater, onSelectItem, onMarkAllAsRead, onMarkAllAsUnread, onToggleRead, onToggleStar, onToggleBookmark, onReorderItems, onSaveAsBookmark, onClose }: FeedPanelProps) { const { isPro, showUpgradeModal } = usePro(); const [viewMode, setViewMode] = useLocalStorage('superflux_viewmode', 'normal'); const compact = viewMode === 'compact'; @@ -675,6 +676,15 @@ export function FeedPanel({ categories, items, selectedFeedId, selectedSource, s {contextMenu.item.isBookmarked ? 'πŸ”–' : '🏷'} {contextMenu.item.isBookmarked ? 'Retirer de Lire plus tard' : 'Lire plus tard'} + {onSaveAsBookmark && ( + + )} )} diff --git a/src/components/SettingsModal.tsx b/src/components/SettingsModal.tsx index 7f735dc..c2836ba 100644 --- a/src/components/SettingsModal.tsx +++ b/src/components/SettingsModal.tsx @@ -815,9 +815,9 @@ export function SettingsModal({ isOpen, onClose, onImportOpml, feedCount = 0, on Ollama (local) - ))} + { mode: 'flux' as const, icon: 'β—ˆ', label: 'Flux', shortcut: '1', pro: false }, + { mode: 'bookmark' as const, icon: 'πŸ”–', label: 'Signets', shortcut: '2', pro: false }, + { mode: 'note' as const, icon: 'πŸ“', label: 'Notes', shortcut: '3', pro: false }, + { mode: 'editor' as const, icon: '✏️', label: 'Γ‰diteur', shortcut: '4', pro: true }, + { mode: 'draw' as const, icon: '🎨', label: 'Dessin', shortcut: '5', pro: true }, + ]).map(tab => { + const locked = tab.pro && !isPro; + return ( + + ); + })} Ctrl+K )} diff --git a/src/components/SuperDraw.tsx b/src/components/SuperDraw.tsx index e4472b9..7a29b0f 100644 --- a/src/components/SuperDraw.tsx +++ b/src/components/SuperDraw.tsx @@ -1,4 +1,5 @@ import { useState, useCallback, useEffect, useRef, type MouseEvent as RMouseEvent } from 'react'; +import type { DrawDoc } from './DrawFileList'; // ─── Types ─────────────────────────────────────────────────────────── @@ -20,15 +21,18 @@ interface DrawElement { interface Camera { x: number; y: number; zoom: number; } type Handle = 'nw' | 'ne' | 'sw' | 'se'; -const STORAGE_KEY = 'superflux_draw'; +interface SuperDrawProps { + doc?: DrawDoc | null; + onUpdateContent?: (id: string, content: string) => void; + onAddDoc?: () => void; +} + const uid = () => Math.random().toString(36).slice(2, 10); +const EMPTY_DATA = { elements: [] as DrawElement[], camera: { x: 0, y: 0, zoom: 1 } }; -function loadData(): { elements: DrawElement[]; camera: Camera } { - try { const r = localStorage.getItem(STORAGE_KEY); if (r) return JSON.parse(r); } catch { /* */ } - return { elements: [], camera: { x: 0, y: 0, zoom: 1 } }; -} -function saveData(els: DrawElement[], cam: Camera) { - try { localStorage.setItem(STORAGE_KEY, JSON.stringify({ elements: els, camera: cam })); } catch { /* */ } +function parseDocContent(doc?: DrawDoc | null): { elements: DrawElement[]; camera: Camera } { + if (!doc || !doc.content) return EMPTY_DATA; + try { return JSON.parse(doc.content); } catch { return EMPTY_DATA; } } // ─── Geometry ──────────────────────────────────────────────────────── @@ -150,21 +154,21 @@ const FONT_SIZES = [12, 16, 20, 28, 36, 48, 64]; // Component // ═════════════════════════════════════════════════════════════════════ -export function SuperDraw() { +export function SuperDraw({ doc, onUpdateContent, onAddDoc }: SuperDrawProps) { const canvasRef = useRef(null); const wrapRef = useRef(null); const lastPtr = useRef<[number, number]>([0, 0]); - const saveTimer = useRef>(); + const saveTimer = useRef>(undefined); - const init = useRef(loadData()); - const [els, setEls] = useState(init.current.elements); - const [cam, setCam] = useState(init.current.camera); + const init = parseDocContent(doc); + const [els, setEls] = useState(init.elements); + const [cam, setCam] = useState(init.camera); const [tool, setTool] = useState('select'); const [sel, setSel] = useState>(new Set()); const [sColor, setSColor] = useState('#1e1e1e'); const [fColor, setFColor] = useState('transparent'); const [sWidth, setSWidth] = useState(2); - const [hist, setHist] = useState([init.current.elements]); + const [hist, setHist] = useState([init.elements]); const [hIdx, setHIdx] = useState(0); const [dark, setDark] = useState(false); const [fontSize, setFontSize] = useState(20); @@ -172,6 +176,23 @@ export function SuperDraw() { const [textValue, setTextValue] = useState(''); const textAreaRef = useRef(null); + // Track doc id to reset state when switching documents + const prevDocId = useRef(doc?.id); + + useEffect(() => { + if (doc?.id !== prevDocId.current) { + prevDocId.current = doc?.id; + const data = parseDocContent(doc); + setEls(data.elements); + setCam(data.camera); + setSel(new Set()); + setHist([data.elements]); + setHIdx(0); + setTextEdit(null); + setTextValue(''); + } + }, [doc]); + // Refs mirroring state for imperative paint const R = useRef({ els, cam, sel }); R.current = { els, cam, sel }; @@ -200,9 +221,12 @@ export function SuperDraw() { // ── Autosave ── useEffect(() => { + if (!doc || !onUpdateContent) return; clearTimeout(saveTimer.current); - saveTimer.current = setTimeout(() => saveData(els, cam), 400); - }, [els, cam]); + saveTimer.current = setTimeout(() => { + onUpdateContent(doc.id, JSON.stringify({ elements: els, camera: cam })); + }, 400); + }, [els, cam, doc, onUpdateContent]); // ── History ── const push = useCallback((next: DrawElement[]) => { @@ -463,6 +487,20 @@ export function SuperDraw() { background: c === 'transparent' ? 'repeating-conic-gradient(#ddd 0% 25%, transparent 0% 50%) 50% / 10px 10px' : c, }); + if (!doc) { + return ( +
+ 🎨 +

Selectionnez ou creez un schema

+ {onAddDoc && ( + + )} +
+ ); + } + return (
{/* Toolbar */} diff --git a/src/contexts/AuthContext.tsx b/src/contexts/AuthContext.tsx index 1597e01..7a37132 100644 --- a/src/contexts/AuthContext.tsx +++ b/src/contexts/AuthContext.tsx @@ -96,21 +96,11 @@ export function AuthProvider({ children }: { children: ReactNode }) { const signOut = useCallback(async () => { const { error } = await supabase.auth.signOut(); if (error) throw error; - // Clear all user data from localStorage - const userDataKeys = [ - 'superflux_feeds', - 'superflux_items', - 'superflux_folders', - 'superflux_favorites_order', - 'superflux_readlater_order', - 'superflux_highlights', - 'superflux_notes', - 'superflux_note_folders', - 'superflux_editor_docs', - 'superflux_editor_folders', - 'superflux_last_sync', - ]; - userDataKeys.forEach(key => localStorage.removeItem(key)); + // Clear ALL user data from localStorage (every superflux_ key) + const keysToRemove = Object.keys(localStorage).filter(k => k.startsWith('superflux_')); + keysToRemove.forEach(key => localStorage.removeItem(key)); + // Reload to reset all in-memory React state + window.location.reload(); }, []); return ( diff --git a/src/index.css b/src/index.css index 949f52b..c4a5ae2 100644 --- a/src/index.css +++ b/src/index.css @@ -728,6 +728,13 @@ body { color: var(--accent, #d4a853); } +.mode-tab--locked { + opacity: 0.4; +} +.mode-tab--locked .mode-tab-icon { + font-size: 12px; +} + .mode-tab-icon { font-size: 15px; line-height: 1; @@ -900,7 +907,8 @@ body { -4px -4px 16px rgba(255, 255, 255, 0.6); } -.dark .bk-blob-card { +.dark .bk-blob-card, +.amoled .bk-blob-card { box-shadow: 6px 6px 24px rgba(0, 0, 0, 0.4), -4px -4px 16px rgba(255, 255, 255, 0.03); @@ -927,7 +935,8 @@ body { z-index: 0; } -.dark .bk-blob-card__blob { opacity: 0.7; } +.dark .bk-blob-card__blob, +.amoled .bk-blob-card__blob { opacity: 0.7; } /* Glassy content overlay */ .bk-blob-card__glass { @@ -945,7 +954,8 @@ body { overflow: hidden; } -.dark .bk-blob-card__glass { +.dark .bk-blob-card__glass, +.amoled .bk-blob-card__glass { background: rgba(15, 15, 18, 0.82); outline-color: rgba(255, 255, 255, 0.06); } @@ -1067,7 +1077,8 @@ body { white-space: nowrap; } -.dark .bk-blob-card__tag { +.dark .bk-blob-card__tag, +.amoled .bk-blob-card__tag { background: rgba(255, 255, 255, 0.06); } @@ -1100,7 +1111,8 @@ body { transition: all 150ms; } -.dark .bk-blob-card__action-btn { background: rgba(255, 255, 255, 0.06); } +.dark .bk-blob-card__action-btn, +.amoled .bk-blob-card__action-btn { background: rgba(255, 255, 255, 0.06); } .bk-blob-card__action-btn:hover { background: var(--bg-active); color: var(--text-primary); } .bk-blob-card__action-btn--delete:hover { color: var(--red); } diff --git a/src/services/bookmarkService.ts b/src/services/bookmarkService.ts index c8324db..e26f288 100644 --- a/src/services/bookmarkService.ts +++ b/src/services/bookmarkService.ts @@ -12,6 +12,7 @@ export interface WebBookmark { tags: string[]; note: string | null; is_read: boolean; + folder: string | null; source: 'chrome' | 'desktop' | 'mobile'; created_at: string; updated_at: string; @@ -91,6 +92,27 @@ export async function toggleBookmarkRead(userId: string, bookmarkId: string, isR return true; } +export async function updateBookmarkFolder( + userId: string, + bookmarkId: string, + folder: string | null, +): Promise { + if (!isSupabaseConfigured) return false; + + const { error } = await supabase + .from('bookmarks') + .update({ folder }) + .eq('id', bookmarkId) + .eq('user_id', userId); + + if (error) { + console.error('[bookmarks] update folder error:', error); + return false; + } + + return true; +} + export function generateBookmarkId(url: string): string { // Simple hash for desktop (sync compatible with Chrome extension's bk- prefix) let hash = 0; diff --git a/src/services/drawDocService.ts b/src/services/drawDocService.ts new file mode 100644 index 0000000..5279efe --- /dev/null +++ b/src/services/drawDocService.ts @@ -0,0 +1,112 @@ +import { supabase, isSupabaseConfigured } from '../lib/supabase'; + +export interface DrawDocRow { + id: string; + title: string; + content: string; + folder: string | null; + created_at: string; + updated_at: string; +} + +export async function fetchDrawDocs(userId: string): Promise { + if (!isSupabaseConfigured) return []; + + const { data, error } = await supabase + .from('draw_documents') + .select('*') + .eq('user_id', userId) + .order('updated_at', { ascending: false }); + + if (error) { + console.error('[draw-docs] fetch error:', error); + return []; + } + + return data ?? []; +} + +export async function upsertDrawDoc( + userId: string, + doc: { id: string; title: string; content: string; folder?: string | null } +): Promise { + if (!isSupabaseConfigured) return null; + + const { data, error } = await supabase + .from('draw_documents') + .upsert({ + id: doc.id, + user_id: userId, + title: doc.title, + content: doc.content, + folder: doc.folder ?? null, + }, { onConflict: 'id,user_id' }) + .select() + .single(); + + if (error) { + console.error('[draw-docs] upsert error:', error); + return null; + } + + return data; +} + +export async function removeDrawDoc(userId: string, docId: string): Promise { + if (!isSupabaseConfigured) return false; + + const { error } = await supabase + .from('draw_documents') + .delete() + .eq('id', docId) + .eq('user_id', userId); + + if (error) { + console.error('[draw-docs] remove error:', error); + return false; + } + + return true; +} + +export async function updateDrawDocContent( + userId: string, + docId: string, + content: string +): Promise { + if (!isSupabaseConfigured) return false; + + const { error } = await supabase + .from('draw_documents') + .update({ content }) + .eq('id', docId) + .eq('user_id', userId); + + if (error) { + console.error('[draw-docs] update content error:', error); + return false; + } + + return true; +} + +export async function updateDrawDocMeta( + userId: string, + docId: string, + meta: { title?: string; folder?: string | null } +): Promise { + if (!isSupabaseConfigured) return false; + + const { error } = await supabase + .from('draw_documents') + .update(meta) + .eq('id', docId) + .eq('user_id', userId); + + if (error) { + console.error('[draw-docs] update meta error:', error); + return false; + } + + return true; +} diff --git a/src/services/licenseService.ts b/src/services/licenseService.ts index c7829f3..d278d22 100644 --- a/src/services/licenseService.ts +++ b/src/services/licenseService.ts @@ -3,8 +3,8 @@ import { supabase } from '../lib/supabase'; export const PRO_LIMITS = { - maxFeeds: 50, - maxFolders: 10, + maxFeeds: 20, + maxFolders: 5, } as const; export const LEMONSQUEEZY_CHECKOUT_URL = 'https://ohmyapps.lemonsqueezy.com/checkout/buy/02f83483-8f23-408f-b960-fc550819ac44'; diff --git a/src/services/llmService.ts b/src/services/llmService.ts index cdd1bc3..158c188 100644 --- a/src/services/llmService.ts +++ b/src/services/llmService.ts @@ -1,7 +1,7 @@ import type { SummaryFormat } from '../types'; // --- Types --- -export type LLMProvider = 'ollama' | 'groq'; +export type LLMProvider = 'ollama' | 'cloud'; export interface LLMConfig { provider: LLMProvider; @@ -9,6 +9,10 @@ export interface LLMConfig { ollamaModel: string; groqApiKey: string; groqModel: string; + mistralApiKey: string; + mistralModel: string; + geminiApiKey: string; + geminiModel: string; } const DEFAULT_CONFIG: LLMConfig = { @@ -17,6 +21,10 @@ const DEFAULT_CONFIG: LLMConfig = { ollamaModel: 'llama3.2:3b', groqApiKey: import.meta.env.VITE_GROQ_API_KEY || '', groqModel: 'llama-3.3-70b-versatile', + mistralApiKey: import.meta.env.VITE_MISTRAL_API_KEY || '', + mistralModel: 'mistral-small-latest', + geminiApiKey: import.meta.env.VITE_GEMINI_API_KEY || '', + geminiModel: 'gemini-2.0-flash', }; // --- Persistence --- @@ -25,15 +33,24 @@ const STORAGE_KEY = 'superflux_llm_config'; export function getLLMConfig(): LLMConfig { const saved = localStorage.getItem(STORAGE_KEY); if (saved) { - return { ...DEFAULT_CONFIG, ...JSON.parse(saved) }; + const parsed = { ...DEFAULT_CONFIG, ...JSON.parse(saved) }; + // Migration: ancien provider 'groq' β†’ 'cloud' + if ((parsed.provider as string) === 'groq') parsed.provider = 'cloud'; + return parsed; } - // Auto-detect: si pas de clΓ© Groq, utiliser Ollama par dΓ©faut - if (!DEFAULT_CONFIG.groqApiKey) { + // Auto-detect: si aucune clΓ© cloud, utiliser Ollama par dΓ©faut + if (!DEFAULT_CONFIG.groqApiKey && !DEFAULT_CONFIG.mistralApiKey && !DEFAULT_CONFIG.geminiApiKey) { return { ...DEFAULT_CONFIG, provider: 'ollama' }; } return DEFAULT_CONFIG; } +/** Retourne true si au moins une clΓ© API cloud est configurΓ©e */ +export function hasAnyCloudKey(config?: LLMConfig): boolean { + const c = config ?? getLLMConfig(); + return !!(c.groqApiKey || c.mistralApiKey || c.geminiApiKey); +} + export function saveLLMConfig(config: Partial) { const current = getLLMConfig(); const merged = { ...current, ...config }; @@ -131,6 +148,120 @@ async function callGroq( return message.trim(); } +async function callMistral( + config: LLMConfig, + systemPrompt: string, + userMessage: string, +): Promise { + if (!config.mistralApiKey) { + throw new Error('ClΓ© API Mistral non configurΓ©e'); + } + + const response = await fetch('https://api.mistral.ai/v1/chat/completions', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${config.mistralApiKey}`, + }, + body: JSON.stringify({ + model: config.mistralModel, + messages: [ + { role: 'system', content: systemPrompt }, + { role: 'user', content: userMessage }, + ], + temperature: 0.3, + }), + }); + + if (response.status === 429) { + throw new Error('Limite Mistral atteinte (rate limit)'); + } + if (!response.ok) { + throw new Error(`Erreur API Mistral (${response.status}): ${response.statusText}`); + } + + const data = await response.json(); + const message = data?.choices?.[0]?.message?.content; + if (!message) { + throw new Error('RΓ©ponse vide de l\'API Mistral'); + } + return message.trim(); +} + +async function callGemini( + config: LLMConfig, + systemPrompt: string, + userMessage: string, +): Promise { + if (!config.geminiApiKey) { + throw new Error('ClΓ© API Gemini non configurΓ©e'); + } + + const url = `https://generativelanguage.googleapis.com/v1beta/models/${config.geminiModel}:generateContent?key=${config.geminiApiKey}`; + + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + system_instruction: { parts: [{ text: systemPrompt }] }, + contents: [{ role: 'user', parts: [{ text: userMessage }] }], + generationConfig: { temperature: 0.3 }, + }), + }); + + if (response.status === 429) { + throw new Error('Limite Gemini atteinte (rate limit)'); + } + if (!response.ok) { + throw new Error(`Erreur API Gemini (${response.status}): ${response.statusText}`); + } + + const data = await response.json(); + const message = data?.candidates?.[0]?.content?.parts?.[0]?.text; + if (!message) { + throw new Error('RΓ©ponse vide de l\'API Gemini'); + } + return message.trim(); +} + +/** Nom du dernier provider cloud utilisΓ© avec succΓ¨s */ +export let lastCloudProvider: string | null = null; + +type CloudCaller = (config: LLMConfig, sys: string, usr: string) => Promise; + +async function callCloud( + config: LLMConfig, + systemPrompt: string, + userMessage: string, +): Promise { + const providers: { name: string; available: boolean; call: CloudCaller }[] = [ + { name: 'Groq', available: !!config.groqApiKey, call: callGroq }, + { name: 'Mistral', available: !!config.mistralApiKey, call: callMistral }, + { name: 'Gemini', available: !!config.geminiApiKey, call: callGemini }, + ]; + + const available = providers.filter(p => p.available); + if (available.length === 0) { + throw new Error('Aucune clΓ© API cloud configurΓ©e (Groq, Mistral ou Gemini). Ajoutez au moins une clΓ© dans .env'); + } + + const errors: string[] = []; + for (const provider of available) { + try { + const result = await provider.call(config, systemPrompt, userMessage); + lastCloudProvider = provider.name; + return result; + } catch (err) { + const msg = err instanceof Error ? err.message : String(err); + errors.push(`${provider.name}: ${msg}`); + console.warn(`[LLM] ${provider.name} Γ©chouΓ©, tentative suivante...`, msg); + } + } + + lastCloudProvider = null; + throw new Error(`Tous les providers cloud ont Γ©chouΓ©:\n${errors.join('\n')}`); +} + // --- Public API (mΓͺme signature que l'ancien groqService) --- export async function summarizeArticle( content: string, @@ -149,7 +280,7 @@ export async function summarizeArticle( if (config.provider === 'ollama') { return callOllama(config, systemPrompt, userMessage); } - return callGroq(config, systemPrompt, userMessage); + return callCloud(config, systemPrompt, userMessage); } // --- Digest multi-articles --- @@ -176,7 +307,7 @@ export async function summarizeDigest(articles: DigestArticle[]): Promise