UNPKG

luhn-generator

Version:

A generator of numbers that passes the validation of Luhn algorithm or Luhn formula, also known as the 'modulus 10' or 'mod 10' algorithm

153 lines (136 loc) 3.85 kB
import arialabelledbyText from '../aria/arialabelledby-text'; import arialabelText from '../aria/arialabel-text'; import nativeTextAlternative from './native-text-alternative'; import formControlValue from './form-control-value'; import subtreeText from './subtree-text'; import titleText from './title-text'; import sanitize from './sanitize'; import isVisible from '../dom/is-visible'; /** * Finds virtual node and calls accessibleTextVirtual() * IMPORTANT: This method requires the composed tree at axe._tree * * @param {HTMLElement} element The HTMLElement * @param {Object} context * @property {Bool} inControlContext * @property {Bool} inLabelledByContext * @return {string} */ function accessibleTextVirtual(virtualNode, context = {}) { const { actualNode } = virtualNode; context = prepareContext(virtualNode, context); // Step 2A, check visibility if (shouldIgnoreHidden(virtualNode, context)) { return ''; } const computationSteps = [ arialabelledbyText, // Step 2B.1 arialabelText, // Step 2C nativeTextAlternative, // Step 2D formControlValue, // Step 2E subtreeText, // Step 2F + Step 2H textNodeValue, // Step 2G (order with 2H does not matter) titleText // Step 2I ]; // Find the first step that returns a non-empty string let accName = computationSteps.reduce((accName, step) => { if (context.startNode === virtualNode) { accName = sanitize(accName); } if (accName !== '') { // yes, whitespace only a11y names halt the algorithm return accName; } return step(virtualNode, context); }, ''); if (context.debug) { axe.log(accName || '{empty-value}', actualNode, context); } return accName; } /** * Return the nodeValue of a node * @param {VirtualNode} element * @return {String} nodeValue value */ function textNodeValue(virtualNode) { if (virtualNode.props.nodeType !== 3) { return ''; } return virtualNode.props.nodeValue; } /** * Check if the * @param {VirtualNode} element * @param {Object} context * @property {VirtualNode[]} processed * @return {Boolean} */ function shouldIgnoreHidden({ actualNode }, context) { if (!actualNode) { return false; } if ( // If the parent isn't ignored, the text node should not be either actualNode.nodeType !== 1 || // If the target of aria-labelledby is hidden, ignore all descendents context.includeHidden ) { return false; } return !isVisible(actualNode, true); } /** * Apply defaults to the context * @param {VirtualNode} element * @param {Object} context * @return {Object} context object with defaults applied */ function prepareContext(virtualNode, context) { const { actualNode } = virtualNode; if (!context.startNode) { context = { startNode: virtualNode, ...context }; } if (!actualNode) { return context; } /** * When `aria-labelledby` directly references a `hidden` element * the element needs to be included in the accessible name. * * When a descendent of the `aria-labelledby` reference is `hidden` * the element should not be included in the accessible name. * * This is done by setting `includeHidden` for the `aria-labelledby` reference. */ if ( actualNode.nodeType === 1 && context.inLabelledByContext && context.includeHidden === undefined ) { context = { includeHidden: !isVisible(actualNode, true), ...context }; } return context; } /** * Check if the node is processed with this context before * @param {VirtualNode} element * @param {Object} context * @property {VirtualNode[]} processed * @return {Boolean} */ accessibleTextVirtual.alreadyProcessed = function alreadyProcessed( virtualnode, context ) { context.processed = context.processed || []; if (context.processed.includes(virtualnode)) { return true; } context.processed.push(virtualnode); return false; }; export default accessibleTextVirtual;