UNPKG

fonteva-design-guide

Version:

## Dev, Build and Test

129 lines (113 loc) 4.94 kB
const validateWcag = (element, tagName) => { let isValid = true; wcagValidations[tagName].forEach(validation => { if (validation.validate(element) === false) { isValid = false; ['fix', 'log'].forEach(action => { if (typeof validation[action] === 'function') { validation[action](element); } }); } }); return isValid; }; const hasChildImageAltText = element => { return ( [...element.querySelectorAll('img')].reduce((altText, imgElement) => { if (imgElement.hasAttribute('alt')) { altText += imgElement.getAttribute('alt'); } return altText; }, '') !== '' ); }; const regexMatchesList = (matchList, testMatch) => { const regex = new RegExp(`[^\\W](${matchList.join('|')})[$\\W]`, 'i'); return regex.test(testMatch); }; const isValidId = (element, id) => element.parentNode.querySelector(`[id^="${id}"]`) !== null; const checkProperty = (component, property) => component[property] !== null && component[property] !== ''; const checkAttribute = (element, attribute) => element.hasAttribute(attribute) && element.hasAttribute(attribute) !== ''; const checkAttributeMatch = (element, attribute, matches) => checkAttribute(element, attribute) && regexMatchesList(matches, element.getAttribute(attribute)); const hasAriaPresentationRole = element => checkAttributeMatch(element, 'aria-role', ['presentation', 'none']); const hasValidAriaLabelledBy = element => checkAttribute(element, 'aria-labelledby') && isValidId(element, element.getAttribute('aria-labelledby')); const hasPresentationAlt = element => checkAttributeMatch(element, 'alt', ['spacer', 'placeholder']); const hasExtraneousAlt = element => checkAttributeMatch(element, 'alt', ['image', 'photo']); const validateLinkOrButton = element => { return ( element.innerText !== '' || // - Visible text inside the tag (checkAttribute(element, 'title') && (element.innerText !== '' || checkAttribute(element, 'aria-label'))) || // - A title attribute checkAttribute(element, 'aria-label') || // - An aria-label attribute hasValidAriaLabelledBy(element) || // - An aria-labelledby attribute with one of more IDs that reference valid elements hasAriaPresentationRole(element) || // - An aria-role of "presentation" or "none" hasChildImageAltText(element) // - An image with an alt attribute ); }; const validateInputField = component => { return component.hasLabel || checkProperty(component, 'ariaLabel'); }; const wcagValidations = { /* <img> - All image tags must have at least one of the following: */ img: [ { validate: element => element.hasAttribute('alt'), // An alt attribute, empty if the image is for presentation not content fix: element => element.setAttribute('alt', ''), log: element => console.debug( `ALT attribute missing from tag:\n\t${element.outerHTML}\n\t(Setting ALT to empty string.)` ) }, { validate: element => !hasPresentationAlt(element), // A non-placeholder/spaces/etc alt attribute fix: element => element.setAttribute('alt', ''), log: element => console.debug(`ALT attribute contains presentation terms:\n\t${element.outerHTML} (Setting ALT to empty string.)`) }, { validate: element => !hasExtraneousAlt(element), // An alt attribute that describes the image without using the word image or photo or similar log: element => console.debug(`ALT attribute contains extraneous description terms:\n\t${element.outerHTML}`) } ], /* <a> - All link tags must have at least one of the following: */ a: [ { validate: validateLinkOrButton, log: element => console.debug(`Link tag does not have accessible text:\n\t${element.outerHTML} (No fix applied)`) } ], /* <button> - All button tags must have at least one of the following: */ button: [ { validate: validateLinkOrButton, log: element => console.debug(`Button tag does not have accessible text:\n\t${element.outerHTML} (No fix applied)`) } ], /* <input> - All input fields must have a label */ input: [ { validate: validateInputField, log: element => console.debug(`Input field does not have an accessible label:\n\t${element.outerHTML} (No fix applied)`) } ] }; export { validateWcag as default };