(issues: Array<A11yIssue>)
| 390 | |
| 391 | const existing = selectorIssues.get(selector) || [] |
| 392 | // Avoid duplicate rule IDs for the same selector |
| 393 | if (!existing.some((e) => e.ruleId === issue.ruleId)) { |
| 394 | existing.push({ ruleId: issue.ruleId, impact }) |
| 395 | selectorIssues.set(selector, existing) |
| 396 | } |
| 397 | } |
| 398 | } |
| 399 | |
| 400 | // Highlight each selector with its most severe issue, but show all in tooltip |
| 401 | for (const [selector, issueList] of selectorIssues) { |
| 402 | // Skip empty lists (shouldn't happen, but guards against undefined) |
| 403 | if (issueList.length === 0) { |
| 404 | continue |
| 405 | } |
| 406 | |
| 407 | // Find most severe impact for highlighting |
| 408 | const mostSevereImpact = issueList.reduce((max, issue) => |
| 409 | SEVERITY_ORDER[issue.impact] > SEVERITY_ORDER[max.impact] ? issue : max, |
| 410 | ).impact |
| 411 | |
| 412 | try { |
| 413 | const elements = document.querySelectorAll(selector) |
| 414 | if (elements.length === 0) { |
| 415 | continue |
| 416 | } |
| 417 | |
| 418 | let highlightedCount = 0 |
| 419 | elements.forEach((el) => { |
| 420 | // Skip elements inside devtools |
| 421 | if (isInsideDevtools(el)) { |
| 422 | return |
| 423 | } |
| 424 | |
| 425 | el.classList.add( |
| 426 | HIGHLIGHT_CLASS, |
| 427 | `${HIGHLIGHT_CLASS}--${mostSevereImpact}`, |
| 428 | ) |
| 429 | |
| 430 | // Add tooltip to first highlighted element only, showing ALL issues |
| 431 | if (highlightedCount === 0) { |
| 432 | const tooltip = createTooltip(issueList, el) |
| 433 | if (tooltip) { |
| 434 | document.body.appendChild(tooltip) |
| 435 | } |
| 436 | } |
| 437 | |
| 438 | highlightedCount++ |
| 439 | }) |
| 440 | } catch (error) { |
| 441 | console.error('[A11y Overlay] Error highlighting element:', error) |
| 442 | } |
| 443 | } |
| 444 | } |
| 445 | |
| 446 | /** |
| 447 | * Clear all highlights from the page |
| 448 | */ |
| 449 | export function clearHighlights(): void { |
no test coverage detected