forked from dequelabs/axe-core
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathget-friendly-uri-end.js
More file actions
143 lines (129 loc) · 3.86 KB
/
Copy pathget-friendly-uri-end.js
File metadata and controls
143 lines (129 loc) · 3.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* 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) {
const 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
*/
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);
}
}
export default getFriendlyUriEnd;