Skip to content

Conversation

@Simon-He95
Copy link
Collaborator

@Simon-He95 Simon-He95 commented Sep 26, 2025

…ferenceNode component

Pull Request Description

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is.
*For example: I'm always frustrated when [...] *

Describe the solution you'd like
A clear and concise description of what you want to happen.

UI/UX changes for Desktop Application
If this PR introduces UI/UX changes, please describe them in detail.

  • Include screenshots or GIFs if applicable to visually demonstrate the changes.
  • Explain the reasoning behind the UI/UX decisions and how they improve the user experience of the desktop application.

Platform Compatibility Notes
If this PR has specific platform compatibility considerations (Windows, macOS, Linux), please describe them here.

  • Are there any platform-specific behaviors or code adjustments?
  • Have you tested on all relevant platforms?

Additional context
Add any other context about the pull request here.


Pull Request Description (中文)

你的功能请求是否与某个问题有关?请描述一下。
请对问题进行清晰扼要的描述。
*例如:我增加了 [...] 的功能 *

请描述你希望的解决方案
请对你希望实现的效果进行清晰扼要的描述。

桌面应用程序的 UI/UX 更改
如果此 PR 引入了 UI/UX 更改,请详细描述它们。

  • 如果适用,请包含屏幕截图或 GIF 以直观地演示更改。
  • 解释 UI/UX 决策背后的原因,以及它们如何改善桌面应用程序的用户体验。

平台兼容性注意事项
如果此 PR 具有特定的平台兼容性考虑因素(Windows、macOS、Linux),请在此处描述。

  • 是否有任何平台特定的行为或代码调整?
  • 你是否已在所有相关平台上进行过测试?

附加背景
在此处添加关于此 Pull Request 的任何其他背景信息。

Summary by CodeRabbit

  • New Features

    • Interactive references: hover to preview referenced content (fetches contextual results) and pointer-driven reveal/hide; click opens the related result in a new tab when available.
    • More consistent reference behavior across messages and threads with improved interaction timing.
  • Chores

    • Updated markdown renderer dependency to the latest beta for compatibility and stability.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 26, 2025

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

📥 Commits

Reviewing files that changed from the base of the PR and between 5846752 and ec86800.

📒 Files selected for processing (1)
  • src/renderer/src/components/markdown/MarkdownRenderer.vue (3 hunks)
 ______________________________________________
< Making your bugs an offer they can't refuse. >
 ----------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).

Tip

You can generate walkthrough in a markdown collapsible section to save space.

Enable the reviews.collapse_walkthrough setting in your project's settings in CodeRabbit to generate walkthrough in a markdown collapsible section.

Walkthrough

Updates vue-renderer-markdown dependency and migrates Markdown rendering to use global setCustomComponents. Moves reference interaction logic into registered custom component with click/hover behavior tied to presenter and stores. Removes local ReferenceNode component and stops passing custom-components/typewriterEffect props to NodeRenderer.

Changes

Cohort / File(s) Summary of changes
Dependencies
package.json
Bumps vue-renderer-markdown from 0.0.54-beta.4 to 0.0.54-beta.6.
Markdown renderer integration
src/renderer/src/components/markdown/MarkdownRenderer.vue
Replaces per-render NodeRenderer custom-components with global setCustomComponents. Registers custom reference component with click/hover handlers using useReferenceStore, usePresenter, nanoid. Wires code_block preview via artifact store with message/thread IDs. Removes custom-components and typewriterEffect propagation to NodeRenderer.
Reference component removal
src/renderer/src/components/markdown/ReferenceNode.vue
Deletes standalone ReferenceNode.vue; previous UI/behavior (click to open, hover to show/hide reference) moved into global custom component.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor U as User
  participant MR as MarkdownRenderer.vue
  participant VRM as vue-renderer-markdown<br/>setCustomComponents
  participant RC as Custom Reference Component
  participant TP as Presenter
  participant RS as ReferenceStore
  participant AS as ArtifactStore

  U->>MR: Render markdown
  MR->>VRM: setCustomComponents({ reference, code_block })
  Note right of VRM: Global registration active

  U->>RC: Click reference
  RC->>TP: getSearchResults(messageId)
  TP-->>RC: results
  alt result URL available
    RC->>U: open new tab (navigate)
  else no result
    RC->>RC: no-op/log
  end

  U->>RC: Mouse enter
  RC->>RS: hide()
  RC->>TP: getSearchResults(messageId)
  TP-->>RC: results
  alt valid index
    RC->>RS: show({ anchorEl: referenceNode, index })
  else invalid
    RC->>RS: hide()
  end

  U->>RC: Mouse leave
  RC->>RS: hide()

  Note over MR,AS: code_block
  MR->>AS: onPreviewCode({ messageId, threadId, code })
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

A hop, a skip, I tweak the Markdown streams—
New refs now dance on hover’s gleam.
With global charms, components sing,
Code blocks wink with preview’s ring.
I thump my paw: dependencies rise—
A tidy burrow, streamlined and wise. 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The PR description consists solely of the template headings and placeholder instructions without any actual descriptions of the problem, solution, UI/UX changes, platform compatibility, or additional context, so it fails to meet the repository’s required template. Please fill out each section of the template with concrete information: describe the problem being addressed, outline the implemented solution, detail any UI/UX changes with visual examples, note platform compatibility considerations and testing, and provide any additional context required by the repository’s PR description guidelines.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title clearly summarizes both the dependency update to vue-renderer-markdown 0.0.54-beta.6 and the removal of the ReferenceNode component, which are the primary changes introduced in this refactor. It is concise, specific, and directly reflects the main modifications in the pull request.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/renderer/src/components/markdown/MarkdownRenderer.vue (1)

33-80: Avoid re-registering global custom components per-render.

setCustomComponents is global; calling it in every component instance can cause redundant registrations under HMR and multiple mounts. Guard it so it runs once.

-setCustomComponents( {
+const __key = '__deepchatMarkdownComponentsConfigured__'
+if (!(globalThis as any)[__key]) {
+setCustomComponents({
@@
-})
+})
+;(globalThis as any)[__key] = true
+}

Please verify that ReferenceNode forwards DOM mouse events so onMouseEnter receives a MouseEvent. If it emits a custom event instead, adjust the listener name to match the component’s emitted event name.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3cb064c and 5846752.

📒 Files selected for processing (3)
  • package.json (1 hunks)
  • src/renderer/src/components/markdown/MarkdownRenderer.vue (3 hunks)
  • src/renderer/src/components/markdown/ReferenceNode.vue (0 hunks)
💤 Files with no reviewable changes (1)
  • src/renderer/src/components/markdown/ReferenceNode.vue
🧰 Additional context used
📓 Path-based instructions (15)
src/renderer/src/**/*

📄 CodeRabbit inference engine (.cursor/rules/i18n.mdc)

src/renderer/src/**/*: All user-facing strings must use i18n keys (avoid hardcoded user-visible text in code)
Use the 'vue-i18n' framework for all internationalization in the renderer
Ensure all user-visible text in the renderer uses the translation system

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/**/*.{vue,ts,js,tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

渲染进程代码放在 src/renderer

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/src/**/*.{vue,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/vue-best-practices.mdc)

src/renderer/src/**/*.{vue,ts,tsx,js,jsx}: Use the Composition API for better code organization and reusability
Implement proper state management with Pinia
Utilize Vue Router for navigation and route management
Leverage Vue's built-in reactivity system for efficient data handling

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/src/**/*.vue

📄 CodeRabbit inference engine (.cursor/rules/vue-best-practices.mdc)

Use scoped styles to prevent CSS conflicts between components

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

src/renderer/**/*.{ts,tsx,vue}: Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError).
Use TypeScript for all code; prefer types over interfaces.
Avoid enums; use const objects instead.
Use arrow functions for methods and computed properties.
Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements.

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/**/*.{vue,ts}

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

Implement lazy loading for routes and components.

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/**/*.{ts,vue}

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

src/renderer/**/*.{ts,vue}: Use useFetch and useAsyncData for data fetching.
Implement SEO best practices using Nuxt's useHead and useSeoMeta.

Use Pinia for frontend state management (do not introduce alternative state libraries)

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
**/*.{ts,tsx,js,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use English for all logs and comments

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Enable and adhere to strict TypeScript typing (avoid implicit any, prefer precise types)

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/{src,shell,floating}/**/*.vue

📄 CodeRabbit inference engine (CLAUDE.md)

src/renderer/{src,shell,floating}/**/*.vue: Use Vue 3 Composition API for all components
All user-facing strings must use i18n keys via vue-i18n (no hard-coded UI strings)
Use Tailwind CSS utilities and ensure styles are scoped in Vue components

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/src/components/**/*

📄 CodeRabbit inference engine (CLAUDE.md)

Organize UI components by feature within src/renderer/src/

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/src/**

📄 CodeRabbit inference engine (AGENTS.md)

Put application code for the Vue app under src/renderer/src (components, stores, views, i18n, lib)

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/src/**/*.{vue,ts}

📄 CodeRabbit inference engine (AGENTS.md)

All user-facing strings in the renderer must use vue-i18n keys defined in src/renderer/src/i18n

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
**/*.{js,jsx,ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

Apply Prettier formatting: single quotes, no semicolons, max width 100

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

Name Vue components in PascalCase (e.g., ChatInput.vue)

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
🧠 Learnings (10)
📓 Common learnings
Learnt from: neoragex2002
PR: ThinkInAIXYZ/deepchat#807
File: src/renderer/src/components/markdown/MarkdownRenderer.vue:58-58
Timestamp: 2025-08-28T08:07:05.182Z
Learning: In src/renderer/src/components/markdown/MarkdownRenderer.vue, the unscoped <style> tag is intentionally used for global prose styles and the anchor .markdown-renderer fix, as confirmed by user neoragex2002.
📚 Learning: 2025-08-28T08:07:05.182Z
Learnt from: neoragex2002
PR: ThinkInAIXYZ/deepchat#807
File: src/renderer/src/components/markdown/MarkdownRenderer.vue:58-58
Timestamp: 2025-08-28T08:07:05.182Z
Learning: In src/renderer/src/components/markdown/MarkdownRenderer.vue, the unscoped <style> tag is intentionally used for global prose styles and the anchor .markdown-renderer fix, as confirmed by user neoragex2002.

Applied to files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
📚 Learning: 2025-07-21T01:47:28.817Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-best-practices.mdc:0-0
Timestamp: 2025-07-21T01:47:28.817Z
Learning: Applies to src/renderer/src/**/*.{vue,ts,tsx,js,jsx} : Use the Composition API for better code organization and reusability

Applied to files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Use <script setup> syntax for concise component definitions.

Applied to files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Use Shadcn Vue, Radix Vue, and Tailwind for components and styling.

Applied to files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
  • package.json
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Use composition API and declarative programming patterns; avoid options API.

Applied to files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Use template syntax for declarative rendering.

Applied to files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
📚 Learning: 2025-09-16T07:06:30.939Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: AGENTS.md:0-0
Timestamp: 2025-09-16T07:06:30.939Z
Learning: Applies to test/{main,renderer}/**/*.{test,spec}.ts : Write tests with Vitest (jsdom) and Vue Test Utils

Applied to files:

  • package.json
📚 Learning: 2025-07-21T01:46:30.354Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-07-21T01:46:30.354Z
Learning: Applies to src/renderer/src/**/* : Use the 'vue-i18n' framework for all internationalization in the renderer

Applied to files:

  • package.json
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Use Vue 3 with TypeScript, leveraging defineComponent and PropType.

Applied to files:

  • package.json
🪛 GitHub Actions: PR Check
src/renderer/src/components/markdown/MarkdownRenderer.vue

[warning] 1-1: Code style issues found by Prettier. Run 'prettier --write' to fix.

🔇 Additional comments (2)
src/renderer/src/components/markdown/MarkdownRenderer.vue (1)

85-114: Unscoped prose styles acknowledged.

Leaving styles unscoped here is intentional for global prose/anchor fixes. No change requested.

Based on learnings

package.json (1)

160-160: Dependency bump LGTM; APIs are exposed
v0.0.54-beta.6 exports setCustomComponents, ReferenceNode, and CodeBlockNode as required.

Comment on lines 12 to 17
import { usePresenter } from '@/composables/usePresenter';
import { useArtifactStore } from '@/stores/artifact';
import { useReferenceStore } from '@/stores/reference';
import { nanoid } from 'nanoid';
import { h, ref } from 'vue';
import NodeRenderer, { CodeBlockNode, ReferenceNode, setCustomComponents } from 'vue-renderer-markdown';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix Prettier violations (no semicolons) and drop unused import.

CI flagged Prettier. Also ref becomes unused after removing referenceNode.

-import { usePresenter } from '@/composables/usePresenter';
-import { useArtifactStore } from '@/stores/artifact';
-import { useReferenceStore } from '@/stores/reference';
-import { nanoid } from 'nanoid';
-import { h, ref } from 'vue';
-import NodeRenderer, { CodeBlockNode, ReferenceNode, setCustomComponents } from 'vue-renderer-markdown';
+import { usePresenter } from '@/composables/usePresenter'
+import { useArtifactStore } from '@/stores/artifact'
+import { useReferenceStore } from '@/stores/reference'
+import { nanoid } from 'nanoid'
+import { h } from 'vue'
+import NodeRenderer, { CodeBlockNode, ReferenceNode, setCustomComponents } from 'vue-renderer-markdown'

Please run: pnpm format

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { usePresenter } from '@/composables/usePresenter';
import { useArtifactStore } from '@/stores/artifact';
import { useReferenceStore } from '@/stores/reference';
import { nanoid } from 'nanoid';
import { h, ref } from 'vue';
import NodeRenderer, { CodeBlockNode, ReferenceNode, setCustomComponents } from 'vue-renderer-markdown';
import { usePresenter } from '@/composables/usePresenter'
import { useArtifactStore } from '@/stores/artifact'
import { useReferenceStore } from '@/stores/reference'
import { nanoid } from 'nanoid'
import { h } from 'vue'
import NodeRenderer, { CodeBlockNode, ReferenceNode, setCustomComponents } from 'vue-renderer-markdown'
🤖 Prompt for AI Agents
In src/renderer/src/components/markdown/MarkdownRenderer.vue around lines 12 to
17, Prettier flagged semicolon violations and the import `ref` is now unused;
remove the trailing semicolons in these import lines and delete the unused `ref`
from the import list, then run the formatter (pnpm format) to apply consistent
styling.

reference: ReferenceNode,
const referenceStore = useReferenceStore()
const threadPresenter = usePresenter('threadPresenter')
const referenceNode = ref<HTMLElement | null>(null)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove unused ref; switch to event target for bounding box.

referenceNode is never assigned, so hover never shows references. The proposed change uses the event target’s bounding rect; remove this ref to avoid dead code.

-const referenceNode = ref<HTMLElement | null>(null)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const referenceNode = ref<HTMLElement | null>(null)
-const referenceNode = ref<HTMLElement | null>(null)
🤖 Prompt for AI Agents
In src/renderer/src/components/markdown/MarkdownRenderer.vue around line 31,
remove the unused declaration "const referenceNode = ref<HTMLElement |
null>(null)" and update the hover handler to use the event target’s
boundingClientRect instead of relying on that ref; ensure you cast/check
event.target as an HTMLElement before calling getBoundingClientRect(), handle
potential nulls, and remove any now-unused imports or references to
referenceNode to avoid dead code.

Comment on lines 33 to 61
setCustomComponents( {
reference: (_props) =>
h(ReferenceNode, {
..._props,
messageId,
threadId,
onClick(){
threadPresenter.getSearchResults(_props.messageId ?? '').then((results) => {
const index = parseInt(_props.node.id)
if (index < results.length) {
window.open(results[index - 1].url, '_blank', 'noopener,noreferrer')
}
})
},
onMouseEnter(){
console.log('Mouse entered')
referenceStore.hideReference()
threadPresenter.getSearchResults(_props.messageId ?? '').then((results) => {
const index = parseInt(_props.node.id)
if (index - 1 < results.length && referenceNode.value) {
referenceStore.showReference(results[index - 1], referenceNode.value.getBoundingClientRect())
}
})
},
onMouseLeave(){
console.log('Mouse left')
referenceStore.hideReference()
}
}),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix off-by-one and missing bounds checks when opening references.

Currently checks index < results.length but then uses results[index - 1], which can skip the last item and underflow for id="1". Also add radix/NaN safety and use the local messageId to avoid empty-string fallbacks.

Apply this diff:

-      onClick(){
-        threadPresenter.getSearchResults(_props.messageId ?? '').then((results) => {
-          const index = parseInt(_props.node.id)
-          if (index < results.length) {
-            window.open(results[index - 1].url, '_blank', 'noopener,noreferrer')
-          }
-        })
-      },
+      onClick: () => {
+        threadPresenter.getSearchResults(messageId).then((results) => {
+          const idx = Number(_props.node.id) - 1
+          if (Number.isInteger(idx) && idx >= 0 && idx < results.length) {
+            window.open(results[idx].url, '_blank', 'noopener,noreferrer')
+          }
+        })
+      },
-      onMouseEnter(){
-        console.log('Mouse entered')
-        referenceStore.hideReference()
-        threadPresenter.getSearchResults(_props.messageId ?? '').then((results) => {
-          const index = parseInt(_props.node.id)
-          if (index - 1 < results.length && referenceNode.value) {
-            referenceStore.showReference(results[index - 1], referenceNode.value.getBoundingClientRect())
-          }
-        })
-      },
-      onMouseLeave(){
-        console.log('Mouse left')
-        referenceStore.hideReference()
-      }
+      onMouseEnter: (e: MouseEvent) => {
+        referenceStore.hideReference()
+        const target = e.currentTarget as HTMLElement | null
+        threadPresenter.getSearchResults(messageId).then((results) => {
+          const idx = Number(_props.node.id) - 1
+          if (target && Number.isInteger(idx) && idx >= 0 && idx < results.length) {
+            referenceStore.showReference(results[idx], target.getBoundingClientRect())
+          }
+        })
+      },
+      onMouseLeave: () => {
+        referenceStore.hideReference()
+      }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
setCustomComponents( {
reference: (_props) =>
h(ReferenceNode, {
..._props,
messageId,
threadId,
onClick(){
threadPresenter.getSearchResults(_props.messageId ?? '').then((results) => {
const index = parseInt(_props.node.id)
if (index < results.length) {
window.open(results[index - 1].url, '_blank', 'noopener,noreferrer')
}
})
},
onMouseEnter(){
console.log('Mouse entered')
referenceStore.hideReference()
threadPresenter.getSearchResults(_props.messageId ?? '').then((results) => {
const index = parseInt(_props.node.id)
if (index - 1 < results.length && referenceNode.value) {
referenceStore.showReference(results[index - 1], referenceNode.value.getBoundingClientRect())
}
})
},
onMouseLeave(){
console.log('Mouse left')
referenceStore.hideReference()
}
}),
setCustomComponents({
reference: (_props) =>
h(ReferenceNode, {
..._props,
messageId,
threadId,
onClick: () => {
threadPresenter.getSearchResults(messageId).then((results) => {
const idx = Number(_props.node.id) - 1
if (Number.isInteger(idx) && idx >= 0 && idx < results.length) {
window.open(results[idx].url, '_blank', 'noopener,noreferrer')
}
})
},
onMouseEnter: (e: MouseEvent) => {
referenceStore.hideReference()
const target = e.currentTarget as HTMLElement | null
threadPresenter.getSearchResults(messageId).then((results) => {
const idx = Number(_props.node.id) - 1
if (target && Number.isInteger(idx) && idx >= 0 && idx < results.length) {
referenceStore.showReference(results[idx], target.getBoundingClientRect())
}
})
},
onMouseLeave: () => {
referenceStore.hideReference()
}
}),
🤖 Prompt for AI Agents
In src/renderer/src/components/markdown/MarkdownRenderer.vue around lines 33 to
61, fix the off-by-one and bounds issues and improve safety: parse the node id
with radix (e.g. parseInt(_props.node.id, 10)), validate it (ensure it's a
number and > 0), and use index-1 to access results only when index <=
results.length; also use the local messageId variable instead of
_props.messageId fallback and add the same validated index/bounds check in both
onClick and onMouseEnter before accessing results and
referenceNode.value.getBoundingClientRect().

@zerob13 zerob13 merged commit 31892a8 into ThinkInAIXYZ:dev Sep 26, 2025
1 of 2 checks passed
zerob13 added a commit that referenced this pull request Sep 26, 2025
* fix: katex style (#926)

* refactor: reorganize artifact processing logic and improve attribute parsing (#927)

* fix(thinkingBlock): pre style (#930)

* refactor: remove DOMPurify dependency and replace MessageBlockThink `v-html` with vue-markdown-renderer (#931)

* refactor: remove DOMPurify dependency and replace MessageBlockThink `v-html` with vue-markdown-renderer

* chore: update

* feat: add Qwen3-VL and Qwen3-Max 0924 (#932)

* refactor: update vue-renderer-markdown to 0.0.54-beta.6 and remove Re… (#934)

* refactor: update vue-renderer-markdown to 0.0.54-beta.6 and remove ReferenceNode component

* chore: format

* chore: version 0.3.7

---------

Co-authored-by: Simon He <57086651+Simon-He95@users.noreply.github.com>
Co-authored-by: yyhhyyyyyy <yyhhyyyyyy8@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants