UNPKG

axe-core

Version:

Accessibility engine for automated Web UI testing

145 lines (131 loc) 3.81 kB
/* eslint no-script-url:0 */ /** * Check if a string contains mostly numbers */ function isMostlyNumbers(str = '') { return ( str.length !== 0 && (str.match(/[0-9]/g) || '').length >= str.length / 2 ); } /** * Spit a string into an array with two pieces, at a given index * @param String string to split * @param Number index at which to split * @return Array */ function splitString(str, splitIndex) { return [str.substring(0, splitIndex), str.substring(splitIndex)]; } function trimRight(str) { return str.replace(/\s+$/, ''); } /** * Take a relative or absolute URL and pull it into it's indivisual pieces * * @param url (string) * @return urlPieces * .protocol The protocol used, e.g. 'https://' * .domain Domain name including sub domains and TLD, e.g. 'docs.deque.com' * .port The port number, e.g. ':8080' * .path Path after the domain, e.g. '/home.html' * .query Query string, e.g. '?user=admin&password=pass' * .hash Hash / internal reference, e.g. '#footer' */ function uriParser(url) { let original = url; let protocol = '', domain = '', port = '', path = '', query = '', hash = ''; if (url.includes('#')) { [url, hash] = splitString(url, url.indexOf('#')); } if (url.includes('?')) { [url, query] = splitString(url, url.indexOf('?')); } if (url.includes('://')) { [protocol, url] = url.split('://'); [domain, url] = splitString(url, url.indexOf('/')); } else if (url.substr(0, 2) === '//') { url = url.substr(2); [domain, url] = splitString(url, url.indexOf('/')); } if (domain.substr(0, 4) === 'www.') { domain = domain.substr(4); } if (domain && domain.includes(':')) { [domain, port] = splitString(domain, domain.indexOf(':')); } path = url; // Whatever is left, must be the path return { original, protocol, domain, port, path, query, hash }; } /** * Try to, at the end of the URI, find a string that a user can identify the URI by * * @param uri The URI to use * @param options * .currentDomain The current domain name (optional) * .maxLength Max length of the returned string (default: 25) * @return string A portion at the end of the uri, no longer than maxLength */ axe.utils.getFriendlyUriEnd = function getFriendlyUriEnd( uri = '', options = {} ) { if ( // Skip certain URIs: uri.length <= 1 || // very short uri.substr(0, 5) === 'data:' || // data URIs are unreadable uri.substr(0, 11) === 'javascript:' || // JS isn't a URL uri.includes('?') // query strings aren't very readable either ) { return; } const { currentDomain, maxLength = 25 } = options; const { path, domain, hash } = uriParser(uri); // Split the path at the last / that has text after it const pathEnd = path.substr( path.substr(0, path.length - 2).lastIndexOf('/') + 1 ); if (hash) { if (pathEnd && (pathEnd + hash).length <= maxLength) { return trimRight(pathEnd + hash); } else if ( pathEnd.length < 2 && hash.length > 2 && hash.length <= maxLength ) { return trimRight(hash); } else { return; } } else if (domain && domain.length < maxLength && path.length <= 1) { // '' or '/' return trimRight(domain + path); } // See if the domain should be returned if ( path === '/' + pathEnd && domain && currentDomain && domain !== currentDomain && (domain + path).length <= maxLength ) { return trimRight(domain + path); } const lastDotIndex = pathEnd.lastIndexOf('.'); if ( // Exclude very short or very long string (lastDotIndex === -1 || lastDotIndex > 1) && (lastDotIndex !== -1 || pathEnd.length > 2) && pathEnd.length <= maxLength && // Exclude index files !pathEnd.match(/index(\.[a-zA-Z]{2-4})?/) && // Exclude files that are likely to be database IDs !isMostlyNumbers(pathEnd) ) { return trimRight(pathEnd); } };