diff --git a/packages/superdoc/src/SuperDoc.test.js b/packages/superdoc/src/SuperDoc.test.js index e2f99ab414..01f0adca19 100644 --- a/packages/superdoc/src/SuperDoc.test.js +++ b/packages/superdoc/src/SuperDoc.test.js @@ -638,6 +638,21 @@ describe('SuperDoc.vue', () => { expect(commentsStoreStub.clearEditorCommentPositions).toHaveBeenCalled(); }); + it('forwards empty comment position payloads to store-level guard', async () => { + const superdocStub = createSuperdocStub(); + const wrapper = await mountComponent(superdocStub); + await nextTick(); + + const options = wrapper.findComponent(SuperEditorStub).props('options'); + options.onCommentLocationsUpdate({ + allCommentPositions: {}, + allCommentIds: [], + }); + await nextTick(); + + expect(commentsStoreStub.handleEditorLocationsUpdate).toHaveBeenCalledWith({}, []); + }); + it('clears PDF selections when viewing mode is active to keep tools hidden', async () => { const superdocStub = createSuperdocStub(); superdocStub.config.documentMode = 'viewing'; diff --git a/packages/superdoc/src/SuperDoc.vue b/packages/superdoc/src/SuperDoc.vue index fde584dd05..2970387ff3 100644 --- a/packages/superdoc/src/SuperDoc.vue +++ b/packages/superdoc/src/SuperDoc.vue @@ -250,7 +250,6 @@ const onEditorReady = ({ editor, presentationEditor }) => { presentationEditor.on('commentPositions', ({ positions }) => { const commentsConfig = proxy.$superdoc.config.modules?.comments; if (!commentsConfig || commentsConfig === false) return; - if (!positions || Object.keys(positions).length === 0) return; if (!shouldRenderCommentsInViewing.value) { commentsStore.clearEditorCommentPositions?.(); return; @@ -453,6 +452,11 @@ const editorOptions = (doc) => { proxy.$superdoc.listeners?.('fonts-resolved')?.length > 0 ? proxy.$superdoc.listeners('fonts-resolved')[0] : null; const useLayoutEngine = proxy.$superdoc.config.useLayoutEngine !== false; + const ydocFragment = doc.ydoc?.getXmlFragment?.('supereditor'); + const ydocMeta = doc.ydoc?.getMap?.('meta'); + const ydocHasContent = (ydocFragment && ydocFragment.length > 0) || (ydocMeta && Boolean(ydocMeta.get('docx'))); + const isNewFile = doc.isNewFile && !ydocHasContent; + const options = { isDebug: proxy.$superdoc.config.isDebug || false, documentId: doc.id, @@ -493,7 +497,7 @@ const editorOptions = (doc) => { onTransaction: onEditorTransaction, ydoc: doc.ydoc, collaborationProvider: doc.provider || null, - isNewFile: doc.isNewFile || false, + isNewFile, handleImageUpload: proxy.$superdoc.config.handleImageUpload, externalExtensions: proxy.$superdoc.config.editorExtensions || [], suppressDefaultDocxStyles: proxy.$superdoc.config.suppressDefaultDocxStyles, diff --git a/packages/superdoc/src/core/SuperDoc.js b/packages/superdoc/src/core/SuperDoc.js index 0c029cba65..e5e2fe6678 100644 --- a/packages/superdoc/src/core/SuperDoc.js +++ b/packages/superdoc/src/core/SuperDoc.js @@ -399,6 +399,9 @@ export class SuperDoc extends EventEmitter { this.superdocStore.init(this.config); const commentsModuleConfig = this.config.modules.comments; this.commentsStore.init(commentsModuleConfig && commentsModuleConfig !== false ? commentsModuleConfig : {}); + if (this.isCollaborative) { + initCollaborationComments(this); + } this.#syncViewingVisibility(); } diff --git a/packages/superdoc/src/core/collaboration/collaboration.test.js b/packages/superdoc/src/core/collaboration/collaboration.test.js index 44114e94df..c21b36e039 100644 --- a/packages/superdoc/src/core/collaboration/collaboration.test.js +++ b/packages/superdoc/src/core/collaboration/collaboration.test.js @@ -2,6 +2,7 @@ import { describe, it, expect, vi, beforeAll, beforeEach, afterEach } from 'vite import * as collaborationModule from './collaboration.js'; import { initCollaborationComments, + loadCommentsFromYdoc, initSuperdocYdoc, makeDocumentsCollaborative, syncCommentsToClients, @@ -292,6 +293,58 @@ describe('collaboration helpers', () => { expect(useCommentMock).toHaveBeenCalledTimes(2); }); + it('initCollaborationComments loads existing comments from ydoc on init', () => { + commentsArray.items = [ + new MockYMap(Object.entries({ commentId: 'c1', text: 'Hello' })), + new MockYMap(Object.entries({ commentId: 'c1', text: 'Duplicate' })), + new MockYMap(Object.entries({ commentId: 'c2', text: 'Another' })), + ]; + + initCollaborationComments(superdoc); + + expect(useCommentMock).toHaveBeenCalledTimes(2); + expect(superdoc.commentsStore.commentsList).toEqual([{ normalized: 'c1' }, { normalized: 'c2' }]); + }); + + it('loadCommentsFromYdoc hydrates comments from importedId and deduplicates by stable key', () => { + commentsArray.items = [ + new MockYMap(Object.entries({ importedId: 'legacy-1', text: 'legacy without commentId' })), + new MockYMap(Object.entries({ importedId: 'legacy-1', text: 'duplicate legacy' })), + new MockYMap(Object.entries({ commentId: 'c2', text: 'normal comment' })), + new MockYMap(Object.entries({ commentId: 'c2', text: 'duplicate normal comment' })), + ]; + superdoc.provider.synced = true; + + const loaded = loadCommentsFromYdoc(superdoc); + + expect(loaded).toBe(true); + expect(useCommentMock).toHaveBeenCalledTimes(2); + expect(useCommentMock).toHaveBeenNthCalledWith( + 1, + expect.objectContaining({ importedId: 'legacy-1', commentId: 'legacy-1' }), + ); + expect(useCommentMock).toHaveBeenNthCalledWith(2, expect.objectContaining({ commentId: 'c2' })); + expect(superdoc.commentsStore.commentsList).toEqual([{ normalized: 'legacy-1' }, { normalized: 'c2' }]); + expect(superdoc.commentsStore.hasSyncedCollaborationComments).toBe(true); + }); + + it('initCollaborationComments re-hydrates store on repeated init without duplicating listeners', () => { + commentsArray.items = [new MockYMap(Object.entries({ commentId: 'c1', text: 'first' }))]; + + initCollaborationComments(superdoc); + expect(commentsArray._observers.size).toBe(1); + expect(superdoc.provider.on).toHaveBeenCalledTimes(1); + expect(superdoc.commentsStore.commentsList).toEqual([{ normalized: 'c1' }]); + + // Simulate store reset after mount; second init should re-hydrate but not add listeners again. + superdoc.commentsStore.commentsList = []; + initCollaborationComments(superdoc); + + expect(commentsArray._observers.size).toBe(1); + expect(superdoc.provider.on).toHaveBeenCalledTimes(1); + expect(superdoc.commentsStore.commentsList).toEqual([{ normalized: 'c1' }]); + }); + it('initCollaborationComments skips when module disabled', () => { superdoc.config.modules.comments = false; initCollaborationComments(superdoc); diff --git a/packages/superdoc/src/core/collaboration/helpers.js b/packages/superdoc/src/core/collaboration/helpers.js index 6f13f3ffb9..974c021757 100644 --- a/packages/superdoc/src/core/collaboration/helpers.js +++ b/packages/superdoc/src/core/collaboration/helpers.js @@ -3,6 +3,51 @@ import useComment from '../../components/CommentsLayer/use-comment'; import { addYComment, updateYComment, deleteYComment } from './collaboration-comments'; +/** + * Load comments from the ydoc into the comments store. + * + * @param {Object} superdoc The SuperDoc instance + * @returns {boolean} True if comments were loaded into the store + */ +export const loadCommentsFromYdoc = (superdoc) => { + if (!superdoc?.ydoc || !superdoc?.commentsStore) return false; + const commentsArray = superdoc.ydoc.getArray('comments'); + const comments = commentsArray.toJSON(); + const seenCommentIdByKey = new Map(); + const filtered = []; + comments.forEach((c) => { + const key = c?.importedId ?? c?.commentId; + if (!key) return; + if (seenCommentIdByKey.has(key)) { + const existingCommentId = seenCommentIdByKey.get(key); + const currentCommentId = c?.commentId; + + if (existingCommentId && currentCommentId && existingCommentId !== currentCommentId) { + console.warn( + `[SuperDoc] Duplicate collaboration comment key "${key}" detected with conflicting commentId values. Keeping first entry and dropping duplicate.`, + { + key, + keptCommentId: existingCommentId, + droppedCommentId: currentCommentId, + }, + ); + } + return; + } + seenCommentIdByKey.set(key, c?.commentId); + if (!c?.commentId) { + filtered.push({ ...c, commentId: key }); + return; + } + filtered.push(c); + }); + superdoc.commentsStore.commentsList = filtered.map((c) => useComment(c)); + if (superdoc.provider?.synced) { + superdoc.commentsStore.hasSyncedCollaborationComments = true; + } + return true; +}; + /** * Initialize sync for comments if the module is enabled * @@ -11,14 +56,27 @@ import { addYComment, updateYComment, deleteYComment } from './collaboration-com */ export const initCollaborationComments = (superdoc) => { if (!superdoc.config.modules.comments || !superdoc.provider) return; + if (superdoc._commentsCollabInitialized) { + loadCommentsFromYdoc(superdoc); + return; + } + superdoc._commentsCollabInitialized = true; // If we have comments and collaboration, wait for sync and then let the store know when its ready + const commentsArray = superdoc.ydoc.getArray('comments'); + const updateCommentsStore = () => loadCommentsFromYdoc(superdoc); + const onSuperDocYdocSynced = () => { + if (!updateCommentsStore()) { + setTimeout(updateCommentsStore, 0); + } // Update the editor comment locations - const parent = superdoc.commentsStore.commentsParentElement; - const ids = superdoc.commentsStore.editorCommentIds; - superdoc.commentsStore.handleEditorLocationsUpdate(parent, ids); - superdoc.commentsStore.hasSyncedCollaborationComments = true; + if (superdoc.commentsStore) { + const parent = superdoc.commentsStore.commentsParentElement; + const ids = superdoc.commentsStore.editorCommentIds; + superdoc.commentsStore.handleEditorLocationsUpdate(parent, ids); + superdoc.commentsStore.hasSyncedCollaborationComments = true; + } superdoc.provider.off('synced', onSuperDocYdocSynced); }; @@ -26,29 +84,23 @@ export const initCollaborationComments = (superdoc) => { // Listen for the synced event superdoc.provider.on('synced', onSuperDocYdocSynced); - // Get the comments map from the Y.Doc - const commentsArray = superdoc.ydoc.getArray('comments'); + // Load any existing comments immediately (in case provider synced before we subscribed) + if (!updateCommentsStore()) { + setTimeout(updateCommentsStore, 0); + } // Observe changes to the comments map commentsArray.observe((event) => { + if (!superdoc.commentsStore) return; // Ignore events if triggered by the current user const currentUser = superdoc.config.user; - const { user = {} } = event.transaction.origin; + const origin = event?.transaction?.origin; + const { user = {} } = origin || {}; if (currentUser.name === user.name && currentUser.email === user.email) return; // Update conversations - const comments = commentsArray.toJSON(); - - const seen = new Set(); - const filtered = []; - comments.forEach((c) => { - if (!seen.has(c.commentId)) { - seen.add(c.commentId); - filtered.push(c); - } - }); - superdoc.commentsStore.commentsList = filtered.map((c) => useComment(c)); + updateCommentsStore(); }); }; diff --git a/packages/superdoc/src/stores/comments-store.js b/packages/superdoc/src/stores/comments-store.js index 66d9192f1a..b4d362f855 100644 --- a/packages/superdoc/src/stores/comments-store.js +++ b/packages/superdoc/src/stores/comments-store.js @@ -635,6 +635,9 @@ export const useCommentsStore = defineStore('comments', () => { const deleteComment = ({ commentId: commentIdToDelete, superdoc }) => { const commentIndex = commentsList.value.findIndex((c) => c.commentId === commentIdToDelete); const comment = commentsList.value[commentIndex]; + if (!comment) { + return; + } const { commentId, importedId } = comment; const { fileId } = comment; @@ -821,6 +824,9 @@ export const useCommentsStore = defineStore('comments', () => { * @returns {void} */ const handleEditorLocationsUpdate = (allCommentPositions) => { + if ((!allCommentPositions || Object.keys(allCommentPositions).length === 0) && commentsList.value.length > 0) { + return; + } editorCommentPositions.value = allCommentPositions || {}; }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9ec92b8636..5772cce6cd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -422,7 +422,7 @@ importers: version: 14.0.3 mintlify: specifier: ^4.2.331 - version: 4.2.331(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.11))(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/node@22.19.8)(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.3))(typescript@5.9.3) + version: 4.2.331(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.11))(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/node@22.19.2)(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.3))(typescript@5.9.3) remark-mdx: specifier: ^3.1.1 version: 3.1.1 @@ -11289,128 +11289,128 @@ snapshots: '@inquirer/ansi@1.0.2': {} - '@inquirer/checkbox@4.3.2(@types/node@22.19.8)': + '@inquirer/checkbox@4.3.2(@types/node@22.19.2)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@22.19.8) + '@inquirer/core': 10.3.2(@types/node@22.19.2) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@22.19.8) + '@inquirer/type': 3.0.10(@types/node@22.19.2) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 22.19.8 + '@types/node': 22.19.2 - '@inquirer/confirm@5.1.21(@types/node@22.19.8)': + '@inquirer/confirm@5.1.21(@types/node@22.19.2)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.8) - '@inquirer/type': 3.0.10(@types/node@22.19.8) + '@inquirer/core': 10.3.2(@types/node@22.19.2) + '@inquirer/type': 3.0.10(@types/node@22.19.2) optionalDependencies: - '@types/node': 22.19.8 + '@types/node': 22.19.2 - '@inquirer/core@10.3.2(@types/node@22.19.8)': + '@inquirer/core@10.3.2(@types/node@22.19.2)': dependencies: '@inquirer/ansi': 1.0.2 '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@22.19.8) + '@inquirer/type': 3.0.10(@types/node@22.19.2) cli-width: 4.1.0 mute-stream: 2.0.0 signal-exit: 4.1.0 wrap-ansi: 6.2.0 yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 22.19.8 + '@types/node': 22.19.2 - '@inquirer/editor@4.2.23(@types/node@22.19.8)': + '@inquirer/editor@4.2.23(@types/node@22.19.2)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.8) - '@inquirer/external-editor': 1.0.3(@types/node@22.19.8) - '@inquirer/type': 3.0.10(@types/node@22.19.8) + '@inquirer/core': 10.3.2(@types/node@22.19.2) + '@inquirer/external-editor': 1.0.3(@types/node@22.19.2) + '@inquirer/type': 3.0.10(@types/node@22.19.2) optionalDependencies: - '@types/node': 22.19.8 + '@types/node': 22.19.2 - '@inquirer/expand@4.0.23(@types/node@22.19.8)': + '@inquirer/expand@4.0.23(@types/node@22.19.2)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.8) - '@inquirer/type': 3.0.10(@types/node@22.19.8) + '@inquirer/core': 10.3.2(@types/node@22.19.2) + '@inquirer/type': 3.0.10(@types/node@22.19.2) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 22.19.8 + '@types/node': 22.19.2 - '@inquirer/external-editor@1.0.3(@types/node@22.19.8)': + '@inquirer/external-editor@1.0.3(@types/node@22.19.2)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.2 optionalDependencies: - '@types/node': 22.19.8 + '@types/node': 22.19.2 '@inquirer/figures@1.0.15': {} - '@inquirer/input@4.3.1(@types/node@22.19.8)': + '@inquirer/input@4.3.1(@types/node@22.19.2)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.8) - '@inquirer/type': 3.0.10(@types/node@22.19.8) + '@inquirer/core': 10.3.2(@types/node@22.19.2) + '@inquirer/type': 3.0.10(@types/node@22.19.2) optionalDependencies: - '@types/node': 22.19.8 + '@types/node': 22.19.2 - '@inquirer/number@3.0.23(@types/node@22.19.8)': + '@inquirer/number@3.0.23(@types/node@22.19.2)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.8) - '@inquirer/type': 3.0.10(@types/node@22.19.8) + '@inquirer/core': 10.3.2(@types/node@22.19.2) + '@inquirer/type': 3.0.10(@types/node@22.19.2) optionalDependencies: - '@types/node': 22.19.8 + '@types/node': 22.19.2 - '@inquirer/password@4.0.23(@types/node@22.19.8)': + '@inquirer/password@4.0.23(@types/node@22.19.2)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@22.19.8) - '@inquirer/type': 3.0.10(@types/node@22.19.8) + '@inquirer/core': 10.3.2(@types/node@22.19.2) + '@inquirer/type': 3.0.10(@types/node@22.19.2) optionalDependencies: - '@types/node': 22.19.8 + '@types/node': 22.19.2 - '@inquirer/prompts@7.9.0(@types/node@22.19.8)': - dependencies: - '@inquirer/checkbox': 4.3.2(@types/node@22.19.8) - '@inquirer/confirm': 5.1.21(@types/node@22.19.8) - '@inquirer/editor': 4.2.23(@types/node@22.19.8) - '@inquirer/expand': 4.0.23(@types/node@22.19.8) - '@inquirer/input': 4.3.1(@types/node@22.19.8) - '@inquirer/number': 3.0.23(@types/node@22.19.8) - '@inquirer/password': 4.0.23(@types/node@22.19.8) - '@inquirer/rawlist': 4.1.11(@types/node@22.19.8) - '@inquirer/search': 3.2.2(@types/node@22.19.8) - '@inquirer/select': 4.4.2(@types/node@22.19.8) + '@inquirer/prompts@7.9.0(@types/node@22.19.2)': + dependencies: + '@inquirer/checkbox': 4.3.2(@types/node@22.19.2) + '@inquirer/confirm': 5.1.21(@types/node@22.19.2) + '@inquirer/editor': 4.2.23(@types/node@22.19.2) + '@inquirer/expand': 4.0.23(@types/node@22.19.2) + '@inquirer/input': 4.3.1(@types/node@22.19.2) + '@inquirer/number': 3.0.23(@types/node@22.19.2) + '@inquirer/password': 4.0.23(@types/node@22.19.2) + '@inquirer/rawlist': 4.1.11(@types/node@22.19.2) + '@inquirer/search': 3.2.2(@types/node@22.19.2) + '@inquirer/select': 4.4.2(@types/node@22.19.2) optionalDependencies: - '@types/node': 22.19.8 + '@types/node': 22.19.2 - '@inquirer/rawlist@4.1.11(@types/node@22.19.8)': + '@inquirer/rawlist@4.1.11(@types/node@22.19.2)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.8) - '@inquirer/type': 3.0.10(@types/node@22.19.8) + '@inquirer/core': 10.3.2(@types/node@22.19.2) + '@inquirer/type': 3.0.10(@types/node@22.19.2) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 22.19.8 + '@types/node': 22.19.2 - '@inquirer/search@3.2.2(@types/node@22.19.8)': + '@inquirer/search@3.2.2(@types/node@22.19.2)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.8) + '@inquirer/core': 10.3.2(@types/node@22.19.2) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@22.19.8) + '@inquirer/type': 3.0.10(@types/node@22.19.2) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 22.19.8 + '@types/node': 22.19.2 - '@inquirer/select@4.4.2(@types/node@22.19.8)': + '@inquirer/select@4.4.2(@types/node@22.19.2)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@22.19.8) + '@inquirer/core': 10.3.2(@types/node@22.19.2) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@22.19.8) + '@inquirer/type': 3.0.10(@types/node@22.19.2) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 22.19.8 + '@types/node': 22.19.2 - '@inquirer/type@3.0.10(@types/node@22.19.8)': + '@inquirer/type@3.0.10(@types/node@22.19.2)': optionalDependencies: - '@types/node': 22.19.8 + '@types/node': 22.19.2 '@isaacs/balanced-match@4.0.1': {} @@ -11762,9 +11762,9 @@ snapshots: '@microsoft/tsdoc@0.16.0': {} - '@mintlify/cli@4.0.935(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.11))(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/node@22.19.8)(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.3))(typescript@5.9.3)': + '@mintlify/cli@4.0.935(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.11))(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/node@22.19.2)(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.3))(typescript@5.9.3)': dependencies: - '@inquirer/prompts': 7.9.0(@types/node@22.19.8) + '@inquirer/prompts': 7.9.0(@types/node@22.19.2) '@mintlify/common': 1.0.713(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.11))(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) '@mintlify/link-rot': 3.0.872(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.11))(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) '@mintlify/models': 0.0.268 @@ -11778,7 +11778,7 @@ snapshots: front-matter: 4.0.2 fs-extra: 11.2.0 ink: 6.3.0(@types/react@19.2.11)(react@19.2.3) - inquirer: 12.3.0(@types/node@22.19.8) + inquirer: 12.3.0(@types/node@22.19.2) js-yaml: 4.1.0 mdast-util-mdx-jsx: 3.2.0 react: 19.2.3 @@ -16850,12 +16850,12 @@ snapshots: inline-style-parser@0.2.7: {} - inquirer@12.3.0(@types/node@22.19.8): + inquirer@12.3.0(@types/node@22.19.2): dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.8) - '@inquirer/prompts': 7.9.0(@types/node@22.19.8) - '@inquirer/type': 3.0.10(@types/node@22.19.8) - '@types/node': 22.19.8 + '@inquirer/core': 10.3.2(@types/node@22.19.2) + '@inquirer/prompts': 7.9.0(@types/node@22.19.2) + '@inquirer/type': 3.0.10(@types/node@22.19.2) + '@types/node': 22.19.2 ansi-escapes: 4.3.2 mute-stream: 2.0.0 run-async: 3.0.0 @@ -18569,9 +18569,9 @@ snapshots: minipass: 3.3.6 yallist: 4.0.0 - mintlify@4.2.331(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.11))(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/node@22.19.8)(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.3))(typescript@5.9.3): + mintlify@4.2.331(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.11))(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/node@22.19.2)(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.3))(typescript@5.9.3): dependencies: - '@mintlify/cli': 4.0.935(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.11))(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/node@22.19.8)(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.3))(typescript@5.9.3) + '@mintlify/cli': 4.0.935(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.11))(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/node@22.19.2)(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.3))(typescript@5.9.3) transitivePeerDependencies: - '@radix-ui/react-popover' - '@types/node'