From d441843cca9b546ac379a0d504813ab3706c728e Mon Sep 17 00:00:00 2001 From: Giulio Leone Date: Mon, 16 Feb 2026 18:55:08 +0100 Subject: [PATCH] fix(#469): deduplicate cursor-interactive elements in snapshot -C (#475) Three fixes to eliminate duplicate entries: 1. Skip elements that only inherit cursor:pointer from a parent (the parent element is captured instead) 2. Broaden dedup by extracting all quoted text from the ARIA tree, not just ref names 3. Add accepted cursor elements to the dedup set to prevent multiple DOM elements with the same text from duplicating Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/snapshot.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/snapshot.ts b/src/snapshot.ts index 7afa705..22caaa4 100644 --- a/src/snapshot.ts +++ b/src/snapshot.ts @@ -233,6 +233,13 @@ async function findCursorInteractiveElements( if (!hasCursorPointer && !hasOnClick && !hasTabIndex) continue; + // Skip elements that only inherit cursor:pointer from an ancestor + // (the ancestor itself will be captured instead) + if (hasCursorPointer && !hasOnClick && !hasTabIndex) { + const parent = el.parentElement; + if (parent && getComputedStyle(parent).cursor === 'pointer') continue; + } + const text = (el.textContent || '').trim().slice(0, 100); if (!text) continue; @@ -287,11 +294,17 @@ export async function getEnhancedSnapshot( // Filter out elements whose text is already captured in the snapshot const existingTexts = new Set(Object.values(refs).map((r) => r.name?.toLowerCase())); + // Also extract quoted strings from the ARIA tree for broader dedup + for (const m of enhancedTree.matchAll(/"([^"]+)"/g)) { + existingTexts.add(m[1].toLowerCase()); + } const additionalLines: string[] = []; for (const el of cursorElements) { - // Skip if text already captured (likely already in ARIA tree) - if (existingTexts.has(el.text.toLowerCase())) continue; + const elTextLower = el.text.toLowerCase(); + // Skip if text already captured in the ARIA tree + if (existingTexts.has(elTextLower)) continue; + existingTexts.add(elTextLower); const ref = nextRef(); const role = el.hasCursorPointer ? 'clickable' : el.hasOnClick ? 'clickable' : 'focusable';