fix: use hasAttribute with known aria list for interactive candidate detection

Replace broken el.hasAttribute("aria-") with a curated list of 27
aria attributes checked via hasAttribute. Each check is O(1).

WAI-ARIA 1.2 defines ~50 aria attributes total per MDN.
Of these ~27 appear on interactive elements such as buttons,
inputs, sliders, and dialogs. The remaining ~20 are structural
container attributes like aria-live, aria-colcount, and
aria-rowspan that only appear on non-interactive containers.
Checking them would not change results.
This commit is contained in:
liuguiyuan
2026-03-31 00:57:44 +08:00
parent 75bc69c0c0
commit f2b6c9dfd2

View File

@@ -1143,6 +1143,43 @@ export default (
* @param {HTMLElement} element - The element to check. * @param {HTMLElement} element - The element to check.
* @returns {boolean} Whether the element is an interactive candidate. * @returns {boolean} Whether the element is an interactive candidate.
*/ */
const INTERACTIVE_ARIA_ATTRS = [
'aria-label',
'aria-labelledby',
'aria-describedby',
'aria-expanded',
'aria-checked',
'aria-selected',
'aria-pressed',
'aria-hidden',
'aria-haspopup',
'aria-controls',
'aria-owns',
'aria-current',
'aria-disabled',
'aria-live',
'aria-modal',
'aria-activedescendant',
'aria-valuenow',
'aria-valuetext',
'aria-valuemax',
'aria-valuemin',
'aria-autocomplete',
'aria-invalid',
'aria-required',
'aria-level',
'aria-sort',
'aria-orientation',
'aria-multiline',
]
function hasAriaAttribute(el) {
for (let i = 0; i < INTERACTIVE_ARIA_ATTRS.length; i++) {
if (el.hasAttribute(INTERACTIVE_ARIA_ATTRS[i])) return true
}
return false
}
function isInteractiveCandidate(element) { function isInteractiveCandidate(element) {
if (!element || element.nodeType !== Node.ELEMENT_NODE) return false if (!element || element.nodeType !== Node.ELEMENT_NODE) return false
@@ -1167,7 +1204,7 @@ export default (
element.hasAttribute('onclick') || element.hasAttribute('onclick') ||
element.hasAttribute('role') || element.hasAttribute('role') ||
element.hasAttribute('tabindex') || element.hasAttribute('tabindex') ||
element.hasAttribute('aria-') || hasAriaAttribute(element) ||
element.hasAttribute('data-action') || element.hasAttribute('data-action') ||
element.getAttribute('contenteditable') === 'true' element.getAttribute('contenteditable') === 'true'