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

156 lines (136 loc) 5.2 kB
import getExplicitRole from './get-explicit-role'; import getImplicitRole from './implicit-role'; import getGlobalAriaAttrs from '../standards/get-global-aria-attrs'; import isFocusable from '../dom/is-focusable'; import { getNodeFromTree } from '../../core/utils'; import AbstractVirtuaNode from '../../core/base/virtual-node/abstract-virtual-node'; // when an element inherits the presentational role from a parent // is not defined in the spec, but through testing it seems to be // when a specific HTML parent relationship is required and that // parent has `role=presentation`, then the child inherits the // role (i.e. table, ul, dl). Further testing has shown that // intermediate elements (such as divs) break this chain only in // Chrome. // // Also, any nested structure chains reset the role (so two nested // lists with the topmost list role=none will not cause the nested // list to inherit the role=none). // // from Scott O'Hara: // // "the expectation for me, in standard html is that element // structures that require specific parent/child relationships, // if the parent is set to presentational that should set the // children to presentational. ala, tables and lists." // "but outside of those specific constructs, i would not expect // role=presentation to do anything to child element roles" const inheritsPresentationChain = { // valid parent elements, any other element will prevent any // children from inheriting a presentational role from a valid // ancestor td: ['tr'], th: ['tr'], tr: ['thead', 'tbody', 'tfoot', 'table'], thead: ['table'], tbody: ['table'], tfoot: ['table'], li: ['ol', 'ul'], // dts and dds can be wrapped in divs and the div will pass through // the presentation role dt: ['dl', 'div'], dd: ['dl', 'div'], div: ['dl'] }; // role presentation inheritance. // Source: https://www.w3.org/TR/wai-aria-1.1/#conflict_resolution_presentation_none function getInheritedRole(vNode, explicitRoleOptions) { const parentNodeNames = inheritsPresentationChain[vNode.props.nodeName]; if (!parentNodeNames) { return null; } // if we can't look at the parent then we can't know if the node // inherits the presentational role or not if (!vNode.parent) { throw new ReferenceError( 'Cannot determine role presentational inheritance of a required parent outside the current scope.' ); } // parent is not a valid ancestor that can inherit presentation if (!parentNodeNames.includes(vNode.parent.props.nodeName)) { return null; } const parentRole = getExplicitRole(vNode.parent, explicitRoleOptions); if ( ['none', 'presentation'].includes(parentRole) && !hasConflictResolution(vNode.parent) ) { return parentRole; } // an explicit role of anything other than presentational will // prevent any children from inheriting a presentational role // from a valid ancestor if (parentRole) { return null; } return getInheritedRole(vNode.parent, explicitRoleOptions); } function resolveImplicitRole(vNode, explicitRoleOptions) { const implicitRole = getImplicitRole(vNode); if (!implicitRole) { return null; } const presentationalRole = getInheritedRole(vNode, explicitRoleOptions); if (presentationalRole) { return presentationalRole; } return implicitRole; } // role conflict resolution // note: Chrome returns a list with resolved role as "generic" // instead of as a list // (e.g. <ul role="none" aria-label><li>hello</li></ul>) // we will return it as a list as that is the best option. // Source: https://www.w3.org/TR/wai-aria-1.1/#conflict_resolution_presentation_none // See also: https://github.com/w3c/aria/issues/1270 function hasConflictResolution(vNode) { const hasGlobalAria = getGlobalAriaAttrs().some(attr => vNode.hasAttr(attr)); return hasGlobalAria || isFocusable(vNode); } /** * Return the semantic role of an element. * * @method getRole * @memberof axe.commons.aria * @instance * @param {Element|VirtualNode} node * @param {Object} options * @param {boolean} options.noImplicit Do not return the implicit role // @deprecated * @param {boolean} options.fallback Allow fallback roles * @param {boolean} options.abstracts Allow role to be abstract * @param {boolean} options.dpub Allow role to be any (valid) doc-* roles * @returns {string|null} Role or null * * @deprecated noImplicit option is deprecated. Use aria.getExplicitRole instead. */ function getRole(node, { noImplicit, ...explicitRoleOptions } = {}) { const vNode = node instanceof AbstractVirtuaNode ? node : getNodeFromTree(node); if (vNode.props.nodeType !== 1) { return null; } const explicitRole = getExplicitRole(vNode, explicitRoleOptions); if (!explicitRole) { return noImplicit ? null : resolveImplicitRole(vNode, explicitRoleOptions); } if (!['presentation', 'none'].includes(explicitRole)) { return explicitRole; } if (hasConflictResolution(vNode)) { // return null if there is a conflict resolution but no implicit // has been set as the explicit role is not the true role return noImplicit ? null : resolveImplicitRole(vNode, explicitRoleOptions); } // role presentation or none and no conflict resolution return explicitRole; } export default getRole;