Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions packages/fluent-editor/src/modules/link/modules/tooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,13 @@ export class LinkTooltip extends BaseTooltip {
if (isTooltipShow) {
return
}

if (this.isInputFocus) {
this.save()
}
this.isHover = true
const linkNode = event.target as HTMLElement
const linkNode = event.target.tagName === 'IMG'
? event.target.parentNode as HTMLElement
: event.target as HTMLElement
Comment on lines +98 to +100
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify unsafe EventTarget access in the changed method and inspect TS strictness settings.
rg -n -C3 'handleMouseEnter\(event: MouseEvent\)|event\.target\.tagName|event\.target\.parentNode' \
  packages/fluent-editor/src/modules/link/modules/tooltip.ts

fd -i 'tsconfig*.json' | while read -r f; do
  echo "== $f =="
  if command -v jq >/dev/null 2>&1; then
    jq '.compilerOptions // {} | {strict, strictNullChecks, noImplicitAny}' "$f" 2>/dev/null || sed -n '1,120p' "$f"
  else
    sed -n '1,120p' "$f"
  fi
done

Repository: opentiny/tiny-editor

Length of output: 1644


🏁 Script executed:

# Find and examine the full context of handleMouseEnter and the listener setup
rg -n -B15 -A15 'handleMouseEnter' packages/fluent-editor/src/modules/link/modules/tooltip.ts

# Also search for the closest() usage that was mentioned
rg -n 'closest' packages/fluent-editor/src/modules/link/modules/tooltip.ts

# Check the LinkBlot.formats definition
rg -n -B5 -A10 'formats\s*\(' packages/fluent-editor/src/modules/link/modules/tooltip.ts

Repository: opentiny/tiny-editor

Length of output: 3007


🏁 Script executed:

# Check all calls to handleMouseEnter in the entire fluent-editor module
rg -n 'handleMouseEnter' packages/fluent-editor/src/modules/link/modules/tooltip.ts

# Also check if it's called from elsewhere in the codebase
rg -rn 'handleMouseEnter' packages/fluent-editor/src/

Repository: opentiny/tiny-editor

Length of output: 498


Use closest() instead of direct parentNode access for safer link node resolution.

The current code assumes IMG elements are direct children of the <a> tag, which breaks for wrapped image structures like <a><span><img></span></a>. The listener already validates that a target or its ancestor is a link using closest(), but handleMouseEnter only checks parentNode, causing it to miss such cases.

Additionally, event.target should be safely narrowed before accessing properties, as it can be null at runtime.

🔧 Proposed fix
-    const linkNode = event.target.tagName === 'IMG'
-      ? event.target.parentNode as HTMLElement
-      : event.target as HTMLElement
+    const target = event.target as HTMLElement | null
+    if (!target) {
+      return
+    }
+    const linkNode = target.closest(`a.${LinkBlot.className}`) as HTMLElement | null
+    if (!linkNode) {
+      return
+    }
📝 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 linkNode = event.target.tagName === 'IMG'
? event.target.parentNode as HTMLElement
: event.target as HTMLElement
const target = event.target as HTMLElement | null
if (!target) {
return
}
const linkNode = target.closest(`a.${LinkBlot.className}`) as HTMLElement | null
if (!linkNode) {
return
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/fluent-editor/src/modules/link/modules/tooltip.ts` around lines 98 -
100, In handleMouseEnter in tooltip.ts the code assumes event.target is non-null
and that an IMG's parentNode is the anchor; instead first narrow event.target
with a runtime check (e.g., ensure event.target is an HTMLElement) and then
resolve the link element using closest('a') (for both IMG and other elements) so
wrapped images like <a><span><img></span></a> are found; replace the
parentNode-based lookup with a closest-based lookup and guard against a null
target before accessing tagName or calling closest.

const preview = LinkBlot.formats(linkNode)
if (!preview || preview.startsWith('#')) {
return
Expand Down
Loading