UNPKG

axe-core

Version:

Accessibility engine for automated Web UI testing

92 lines (80 loc) 2.79 kB
/* global axe, dom, window */ function walkDomNode(node, functor) { if (functor(node.actualNode) !== false) { node.children.forEach(child => walkDomNode(child, functor)); } } var blockLike = ['block', 'list-item', 'table', 'flex', 'grid', 'inline-block']; function isBlock(elm) { var display = window.getComputedStyle(elm).getPropertyValue('display'); return (blockLike.includes(display) || display.substr(0, 6) === 'table-'); } function getBlockParent (node) { // Find the closest parent let parentBlock = dom.getComposedParent(node); while (parentBlock && !isBlock(parentBlock)) { parentBlock = dom.getComposedParent(parentBlock); } return axe.utils.getNodeFromTree(axe._tree[0], parentBlock); } /** * Determines if an element is within a text block * @param {Element} node [description] * @return {Boolean} [description] */ dom.isInTextBlock = function isInTextBlock(node) { /* eslint complexity: ["error",17]*/ if (isBlock(node)) { // Ignore if the link is a block return false; } // Find all the text part of the parent block not in a link, and all the text in a link const virtualParent = getBlockParent(node); let parentText = ''; let linkText = ''; let inBrBlock = 0; // We want to ignore hidden text, and if br / hr is used, only use the section of the parent // that has the link we're looking at walkDomNode(virtualParent, function (currNode) { // We're already passed it, skip everything else if (inBrBlock === 2) { return false; } if (currNode.nodeType === 3) { // Add the text to the parent parentText += currNode.nodeValue; } // Ignore any node that's not an element (or text as above) if (currNode.nodeType !== 1) { return; } var nodeName = (currNode.nodeName || '').toUpperCase(); // BR and HR elements break the line if (['BR', 'HR'].includes(nodeName)) { if (inBrBlock === 0) { parentText = ''; linkText = ''; } else { inBrBlock = 2; } // Don't walk nodes with content not displayed on screen. } else if (currNode.style.display === 'none' || currNode.style.overflow === 'hidden' || !['', null, 'none'].includes(currNode.style.float) || !['', null, 'relative'].includes(currNode.style.position)) { return false; // Don't walk links, we're only interested in what's not in them. } else if ((nodeName === 'A' && currNode.href) || (currNode.getAttribute('role') || '').toLowerCase() === 'link') { if (currNode === node) { inBrBlock = 1; } // Grab all the text from this element, but don't walk down it's children linkText += currNode.textContent; return false; } }); parentText = axe.commons.text.sanitize(parentText); linkText = axe.commons.text.sanitize(linkText); return (parentText.length > linkText.length); };