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
111 lines (92 loc) • 2.95 kB
JavaScript
import isValidRole from './is-valid-role';
import getImplicitRole from './implicit-role';
import getRoleType from './get-role-type';
import isAriaRoleAllowedOnElement from './is-aria-role-allowed-on-element';
import { tokenList, isHtmlElement, matchesSelector } from '../../core/utils';
// dpub roles which are subclassing roles that are implicit on some native
// HTML elements (img, link, etc.)
const dpubRoles = [
'doc-backlink',
'doc-biblioentry',
'doc-biblioref',
'doc-cover',
'doc-endnote',
'doc-glossref',
'doc-noteref'
];
/**
* Returns all roles applicable to element in a list
*
* @method getRoleSegments
* @private
* @param {Element} node
* @returns {Array} Roles list or empty list
*/
function getRoleSegments(node) {
let roles = [];
if (!node) {
return roles;
}
if (node.hasAttribute('role')) {
const nodeRoles = tokenList(node.getAttribute('role').toLowerCase());
roles = roles.concat(nodeRoles);
}
if (node.hasAttributeNS('http://www.idpf.org/2007/ops', 'type')) {
const epubRoles = tokenList(
node.getAttributeNS('http://www.idpf.org/2007/ops', 'type').toLowerCase()
).map(role => `doc-${role}`);
roles = roles.concat(epubRoles);
}
// filter invalid roles
roles = roles.filter(role => isValidRole(role));
return roles;
}
/**
* gets all unallowed roles for a given node
* @method getElementUnallowedRoles
* @param {Object} node HTMLElement to validate
* @param {String} tagName tag name of a node
* @param {String} allowImplicit option to allow implicit roles, defaults to true
* @return {Array<String>} retruns an array of roles that are not allowed on the given node
*/
function getElementUnallowedRoles(node, allowImplicit = true) {
const tagName = node.nodeName.toUpperCase();
// by pass custom elements
if (!isHtmlElement(node)) {
return [];
}
const roleSegments = getRoleSegments(node);
const implicitRole = getImplicitRole(node);
// stores all roles that are not allowed for a specific element most often an element only has one explicit role
const unallowedRoles = roleSegments.filter(role => {
// if role and implicit role are same, when allowImplicit: true
// ignore as it is a redundant role
if (allowImplicit && role === implicitRole) {
return false;
}
// if role is a dpub role make sure it's used on an element with a valid
// implicit role fallback
if (allowImplicit && dpubRoles.includes(role)) {
const roleType = getRoleType(role);
if (implicitRole !== roleType) {
return true;
}
}
// Edge case:
// setting implicit role row on tr element is allowed when child of table[role='grid']
if (
!allowImplicit &&
!(
role === 'row' &&
tagName === 'TR' &&
matchesSelector(node, 'table[role="grid"] > tr')
)
) {
return true;
}
// check if role is allowed on element
return !isAriaRoleAllowedOnElement(node, role);
});
return unallowedRoles;
}
export default getElementUnallowedRoles;