Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(region): add option to match nodes as region #2249

Merged
merged 1 commit into from
May 26, 2020
Merged
Show file tree
Hide file tree
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
16 changes: 11 additions & 5 deletions lib/checks/navigation/region-evaluate.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as dom from '../../commons/dom';
import * as aria from '../../commons/aria';
import * as text from '../../commons/text';
import matches from '../../commons/matches';
import { matchesSelector } from '../../core/utils';
import cache from '../../core/base/cache';

Expand All @@ -13,7 +14,7 @@ const implicitLandmarks = landmarkRoles
.filter(r => r !== null);

// Check if the current element is a landmark
function isRegion(virtualNode) {
function isRegion(virtualNode, options) {
const node = virtualNode.actualNode;
const explicitRole = aria.getRole(node, { noImplicit: true });
const ariaLive = (node.getAttribute('aria-live') || '').toLowerCase().trim();
Expand All @@ -30,6 +31,11 @@ function isRegion(virtualNode) {
return explicitRole === 'dialog' || landmarkRoles.includes(explicitRole);
}

// Check if node matches an option
if (options.regionMatcher && matches(virtualNode, options.regionMatcher)) {
return true;
}

// Check if the node matches any of the CSS selectors of implicit landmarks
return implicitLandmarks.some(implicitSelector => {
let matches = matchesSelector(node, implicitSelector);
Expand All @@ -46,11 +52,11 @@ function isRegion(virtualNode) {
/**
* Find all visible elements not wrapped inside a landmark or skiplink
*/
function findRegionlessElms(virtualNode) {
function findRegionlessElms(virtualNode, options) {
const node = virtualNode.actualNode;
// End recursion if the element is a landmark, skiplink, or hidden content
if (
isRegion(virtualNode) ||
isRegion(virtualNode, options) ||
(dom.isSkipLink(virtualNode.actualNode) &&
dom.getElementByReference(virtualNode.actualNode, 'href')) ||
!dom.isVisible(node, true)
Expand All @@ -77,7 +83,7 @@ function findRegionlessElms(virtualNode) {
} else {
return virtualNode.children
.filter(({ actualNode }) => actualNode.nodeType === 1)
.map(findRegionlessElms)
.map(vNode => findRegionlessElms(vNode, options))
.reduce((a, b) => a.concat(b), []); // flatten the results
}
}
Expand All @@ -89,7 +95,7 @@ function regionEvaluate(node, options, virtualNode) {
}

const tree = axe._tree;
regionlessNodes = findRegionlessElms(tree[0])
regionlessNodes = findRegionlessElms(tree[0], options)
// Find first parent marked as having region descendant (or body) and
// return the node right before it as the "outer" element
.map(vNode => {
Expand Down
Loading